GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: monotonic_resource.hpp
Date: 2025-12-23 17:38:58
Exec Total Coverage
Lines: 3 3 100.0%
Functions: 1 1 100.0%
Branches: 0 0 -%

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