LCOV - code coverage report
Current view: top level - json - monotonic_resource.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 3 3
Test Date: 2025-12-23 17:21:58 Functions: 100.0 % 1 1

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3              : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
       4              : //
       5              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       6              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       7              : //
       8              : // Official repository: https://github.com/boostorg/json
       9              : //
      10              : 
      11              : #ifndef BOOST_JSON_MONOTONIC_RESOURCE_HPP
      12              : #define BOOST_JSON_MONOTONIC_RESOURCE_HPP
      13              : 
      14              : #include <boost/container/pmr/memory_resource.hpp>
      15              : #include <boost/json/detail/config.hpp>
      16              : #include <boost/json/memory_resource.hpp>
      17              : #include <boost/json/storage_ptr.hpp>
      18              : #include <cstddef>
      19              : #include <utility>
      20              : 
      21              : namespace boost {
      22              : namespace json {
      23              : 
      24              : #ifdef _MSC_VER
      25              : #pragma warning(push)
      26              : #pragma warning(disable: 4251) // class needs to have dll-interface to be used by clients of class
      27              : #pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
      28              : #endif
      29              : 
      30              : //----------------------------------------------------------
      31              : 
      32              : /** A dynamically allocating resource with a trivial deallocate
      33              : 
      34              :     This memory resource is a special-purpose resource
      35              :     that releases allocated memory only when the resource
      36              :     is destroyed (or when @ref release is called).
      37              :     It has a trivial deallocate function; that is, the
      38              :     metafunction @ref is_deallocate_trivial returns `true`.
      39              : \n
      40              :     The resource can be constructed with an initial buffer.
      41              :     If there is no initial buffer, or if the buffer is
      42              :     exhausted, subsequent dynamic allocations are made from
      43              :     the system heap. The size of buffers obtained in this
      44              :     fashion follow a geometric progression.
      45              : \n
      46              :     The purpose of this resource is to optimize the use
      47              :     case for performing many allocations, followed by
      48              :     deallocating everything at once. This is precisely the
      49              :     pattern of memory allocation which occurs when parsing:
      50              :     allocation is performed for each parsed element, and
      51              :     when the the resulting @ref value is no longer needed,
      52              :     the entire structure is destroyed. However, it is not
      53              :     suited for modifying the value after parsing is
      54              :     complete; reallocations waste memory, since the
      55              :     older buffer is not reclaimed until the resource
      56              :     is destroyed.
      57              : 
      58              :     @par Example
      59              : 
      60              :     This parses a JSON text into a value which uses a local
      61              :     stack buffer, then prints the result.
      62              : 
      63              :     @code
      64              : 
      65              :     unsigned char buf[ 4000 ];
      66              :     monotonic_resource mr( buf );
      67              : 
      68              :     // Parse the string, using our memory resource
      69              :     auto const jv = parse( "[1,2,3]", &mr );
      70              : 
      71              :     // Print the JSON
      72              :     std::cout << jv;
      73              : 
      74              :     @endcode
      75              : 
      76              :     @note The total amount of memory dynamically
      77              :     allocated is monotonically increasing; That is,
      78              :     it never decreases.
      79              : 
      80              :     @par Thread Safety
      81              :     Members of the same instance may not be
      82              :     called concurrently.
      83              : 
      84              :     @see
      85              :         https://en.wikipedia.org/wiki/Region-based_memory_management
      86              : */
      87              : class
      88              :     BOOST_JSON_DECL
      89              :     BOOST_SYMBOL_VISIBLE
      90              : monotonic_resource final
      91              :     : public container::pmr::memory_resource
      92              : {
      93              :     struct block;
      94              :     struct block_base
      95              :     {
      96              :         void* p;
      97              :         std::size_t avail;
      98              :         std::size_t size;
      99              :         block_base* next;
     100              :     };
     101              : 
     102              :     block_base buffer_;
     103              :     block_base* head_ = &buffer_;
     104              :     std::size_t next_size_ = 1024;
     105              :     storage_ptr upstream_;
     106              : 
     107              :     static constexpr std::size_t min_size_ = 1024;
     108              :     inline static constexpr std::size_t max_size();
     109              :     inline static std::size_t round_pow2(
     110              :         std::size_t n) noexcept;
     111              :     inline static std::size_t next_pow2(
     112              :         std::size_t n) noexcept;
     113              : 
     114              : public:
     115              :     /// Copy constructor (deleted)
     116              :     monotonic_resource(
     117              :         monotonic_resource const&) = delete;
     118              : 
     119              :     /// Copy assignment (deleted)
     120              :     monotonic_resource& operator=(
     121              :         monotonic_resource const&) = delete;
     122              : 
     123              :     /** Destructor
     124              : 
     125              :         Deallocates all the memory owned by this resource.
     126              : 
     127              :         @par Effects
     128              :         @code
     129              :         this->release();
     130              :         @endcode
     131              : 
     132              :         @par Complexity
     133              :         Linear in the number of deallocations performed.
     134              : 
     135              :         @par Exception Safety
     136              :         No-throw guarantee.
     137              :     */
     138              :     ~monotonic_resource();
     139              : 
     140              :     /** Constructor
     141              : 
     142              :         This constructs the resource and indicates
     143              :         that the first internal dynamic allocation
     144              :         shall be at least `initial_size` bytes.
     145              :     \n
     146              :         This constructor is guaranteed not to perform
     147              :         any dynamic allocations.
     148              : 
     149              :         @par Complexity
     150              :         Constant.
     151              : 
     152              :         @par Exception Safety
     153              :         No-throw guarantee.
     154              : 
     155              :         @param initial_size The size of the first
     156              :         internal dynamic allocation. If this is lower
     157              :         than the implementation-defined lower limit, then
     158              :         the lower limit is used instead.
     159              : 
     160              :         @param upstream An optional upstream memory resource
     161              :         to use for performing internal dynamic allocations.
     162              :         If this parameter is omitted, the default resource
     163              :         is used.
     164              :     */
     165              :     explicit
     166              :     monotonic_resource(
     167              :         std::size_t initial_size = 1024,
     168              :         storage_ptr upstream = {}) noexcept;
     169              : 
     170              :     /** Constructor
     171              : 
     172              :         This constructs the resource and indicates that
     173              :         subsequent allocations should use the specified
     174              :         caller-owned buffer.
     175              :         When this buffer is exhausted, dynamic allocations
     176              :         from the upstream resource are made.
     177              :     \n
     178              :         This constructor is guaranteed not to perform
     179              :         any dynamic allocations.
     180              : 
     181              :         @par Complexity
     182              :         Constant.
     183              : 
     184              :         @par Exception Safety
     185              :         No-throw guarantee.
     186              : 
     187              :         @param buffer The buffer to use.
     188              :         Ownership is not transferred; the caller is
     189              :         responsible for ensuring that the lifetime of
     190              :         the buffer extends until the resource is destroyed.
     191              : 
     192              :         @param size The number of valid bytes pointed
     193              :         to by `buffer`.
     194              : 
     195              :         @param upstream An optional upstream memory resource
     196              :         to use for performing internal dynamic allocations.
     197              :         If this parameter is omitted, the default resource
     198              :         is used.
     199              :     */
     200              :     /** @{ */
     201              :     monotonic_resource(
     202              :         unsigned char* buffer,
     203              :         std::size_t size,
     204              :         storage_ptr upstream = {}) noexcept;
     205              : 
     206              : #if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
     207              :     monotonic_resource(
     208              :         std::byte* buffer,
     209              :         std::size_t size,
     210              :         storage_ptr upstream) noexcept
     211              :         : monotonic_resource(reinterpret_cast<
     212              :             unsigned char*>(buffer), size,
     213              :                 std::move(upstream))
     214              :     {
     215              :     }
     216              : #endif
     217              :     /** @} */
     218              : 
     219              :     /** Constructor
     220              : 
     221              :         This constructs the resource and indicates that
     222              :         subsequent allocations should use the specified
     223              :         caller-owned buffer.
     224              :         When this buffer is exhausted, dynamic allocations
     225              :         from the upstream resource are made.
     226              :     \n
     227              :         This constructor is guaranteed not to perform
     228              :         any dynamic allocations.
     229              : 
     230              :         @par Complexity
     231              :         Constant.
     232              : 
     233              :         @par Exception Safety
     234              :         No-throw guarantee.
     235              : 
     236              :         @param buffer The buffer to use.
     237              :         Ownership is not transferred; the caller is
     238              :         responsible for ensuring that the lifetime of
     239              :         the buffer extends until the resource is destroyed.
     240              : 
     241              :         @param upstream An optional upstream memory resource
     242              :         to use for performing internal dynamic allocations.
     243              :         If this parameter is omitted, the default resource
     244              :         is used.
     245              :     */
     246              :     /** @{ */
     247              :     template<std::size_t N>
     248              :     explicit
     249            2 :     monotonic_resource(
     250              :         unsigned char(&buffer)[N],
     251              :         storage_ptr upstream = {}) noexcept
     252              :         : monotonic_resource(&buffer[0],
     253            2 :             N, std::move(upstream))
     254              :     {
     255            2 :     }
     256              : 
     257              : #if defined(__cpp_lib_byte) || defined(BOOST_JSON_DOCS)
     258              :     template<std::size_t N>
     259              :     explicit
     260              :     monotonic_resource(
     261              :         std::byte(&buffer)[N],
     262              :         storage_ptr upstream = {}) noexcept
     263              :         : monotonic_resource(&buffer[0],
     264              :             N, std::move(upstream))
     265              :     {
     266              :     }
     267              : #endif
     268              :     /** @} */
     269              : 
     270              : #ifndef BOOST_JSON_DOCS
     271              :     // Safety net for accidental buffer overflows
     272              :     template<std::size_t N>
     273              :     monotonic_resource(
     274              :         unsigned char(&buffer)[N],
     275              :         std::size_t n,
     276              :         storage_ptr upstream = {}) noexcept
     277              :         : monotonic_resource(&buffer[0],
     278              :             n, std::move(upstream))
     279              :     {
     280              :         // If this goes off, check your parameters
     281              :         // closely, chances are you passed an array
     282              :         // thinking it was a pointer.
     283              :         BOOST_ASSERT(n <= N);
     284              :     }
     285              : 
     286              : #ifdef __cpp_lib_byte
     287              :     // Safety net for accidental buffer overflows
     288              :     template<std::size_t N>
     289              :     monotonic_resource(
     290              :         std::byte(&buffer)[N],
     291              :         std::size_t n,
     292              :         storage_ptr upstream = {}) noexcept
     293              :         : monotonic_resource(&buffer[0],
     294              :             n, std::move(upstream))
     295              :     {
     296              :         // If this goes off, check your parameters
     297              :         // closely, chances are you passed an array
     298              :         // thinking it was a pointer.
     299              :         BOOST_ASSERT(n <= N);
     300              :     }
     301              : #endif
     302              : #endif
     303              : 
     304              :     /** Release all allocated memory.
     305              : 
     306              :         This function deallocates all allocated memory.
     307              :         If an initial buffer was provided upon construction,
     308              :         then all of the bytes will be available again for
     309              :         allocation. Allocated memory is deallocated even
     310              :         if deallocate has not been called for some of
     311              :         the allocated blocks.
     312              : 
     313              :         @par Complexity
     314              :         Linear in the number of deallocations performed.
     315              : 
     316              :         @par Exception Safety
     317              :         No-throw guarantee.
     318              :     */
     319              :     void
     320              :     release() noexcept;
     321              : 
     322              : protected:
     323              : #ifndef BOOST_JSON_DOCS
     324              :     void*
     325              :     do_allocate(
     326              :         std::size_t n,
     327              :         std::size_t align) override;
     328              : 
     329              :     void
     330              :     do_deallocate(
     331              :         void* p,
     332              :         std::size_t n,
     333              :         std::size_t align) override;
     334              : 
     335              :     bool
     336              :     do_is_equal(
     337              :         memory_resource const& mr) const noexcept override;
     338              : #endif
     339              : };
     340              : 
     341              : #ifdef _MSC_VER
     342              : #pragma warning(pop)
     343              : #endif
     344              : 
     345              : template<>
     346              : struct is_deallocate_trivial<
     347              :     monotonic_resource>
     348              : {
     349              :     static constexpr bool value = true;
     350              : };
     351              : 
     352              : } // namespace json
     353              : } // namespace boost
     354              : 
     355              : #endif
        

Generated by: LCOV version 2.1