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

Generated by: LCOV version 2.1