LCOV - code coverage report
Current view: top level - json - monotonic_resource.hpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 3 3
Test Date: 2026-03-05 09:04:27 Functions: 100.0 % 1 1

           TLA  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 HIT           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.3