GCC Code Coverage Report


Directory: libs/url/
File: boost/url/grammar/recycled.hpp
Date: 2024-03-13 19:32:03
Exec Total Coverage
Lines: 9 9 100.0%
Functions: 9 9 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 //
2 // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/url
8 //
9
10 #ifndef BOOST_URL_GRAMMAR_RECYCLED_HPP
11 #define BOOST_URL_GRAMMAR_RECYCLED_HPP
12
13 #include <boost/url/detail/config.hpp>
14 #include <boost/url/grammar/detail/recycled.hpp>
15 #include <atomic>
16 #include <cstddef>
17 #include <type_traits>
18 #include <stddef.h> // ::max_align_t
19
20 #if !defined(BOOST_URL_DISABLE_THREADS)
21 # include <mutex>
22 #endif
23
24 namespace boost {
25 namespace urls {
26 namespace grammar {
27
28 /** Provides an aligned storage buffer aligned for T
29 */
30 #ifdef BOOST_URL_DOCS
31 template<class T>
32 struct aligned_storage
33 {
34 /** Return a pointer to the aligned storage area
35 */
36 void* addr() noexcept;
37
38 /** Return a pointer to the aligned storage area
39 */
40 void const* addr() const noexcept;
41 };
42 #else
43 template<class T>
44 using aligned_storage =
45 detail::aligned_storage_impl<
46 detail::nearest_pow2(sizeof(T), 64),
47 (alignof(::max_align_t) > alignof(T)) ?
48 alignof(::max_align_t) : alignof(T)>;
49 #endif
50
51 //------------------------------------------------
52
53 /** A thread-safe collection of instances of T
54
55 Instances of this type may be used to control
56 where recycled instances of T come from when
57 used with @ref recycled_ptr.
58
59 @par Example
60 @code
61 static recycled< std::string > bin;
62
63 recycled_ptr< std::string > ps( bin );
64
65 // Put the string into a known state
66 ps->clear();
67 @endcode
68
69 @see
70 @ref recycled_ptr.
71 */
72 template<class T>
73 class recycled
74 {
75 public:
76 /** Destructor
77
78 All recycled instances of T are destroyed.
79 Undefined behavior results if there are
80 any @ref recycled_ptr which reference
81 this recycle bin.
82 */
83 ~recycled();
84
85 /** Constructor
86 */
87 constexpr recycled() = default;
88
89 private:
90 template<class>
91 friend class recycled_ptr;
92
93 struct U
94 {
95 T t;
96 U* next = nullptr;
97
98 #if !defined(BOOST_URL_DISABLE_THREADS)
99 std::atomic<
100 std::size_t> refs;
101 #else
102 std::size_t refs;
103 #endif
104
105
106 5 U()
107 5 : refs{1}
108 {
109 5 }
110 };
111
112 struct report;
113
114 U* acquire();
115 void release(U* u) noexcept;
116
117 U* head_ = nullptr;
118
119 #if !defined(BOOST_URL_DISABLE_THREADS)
120 std::mutex m_;
121 #endif
122 };
123
124 //------------------------------------------------
125
126 /** A pointer to shared instance of T
127
128 This is a smart pointer container which can
129 acquire shared ownership of an instance of
130 `T` upon or after construction. The instance
131 is guaranteed to be in a valid, but unknown
132 state. Every recycled pointer references
133 a valid recycle bin.
134
135 @par Example
136 @code
137 static recycled< std::string > bin;
138
139 recycled_ptr< std::string > ps( bin );
140
141 // Put the string into a known state
142 ps->clear();
143 @endcode
144
145 @tparam T the type of object to
146 acquire, which must be
147 <em>DefaultConstructible</em>.
148 */
149 template<class T>
150 class recycled_ptr
151 {
152 // T must be default constructible!
153 static_assert(
154 std::is_default_constructible<T>::value,
155 "T must be DefaultConstructible");
156
157 friend class recycled<T>;
158
159 using B = recycled<T>;
160 using U = typename B::U;
161
162 B* bin_ = nullptr;
163 U* p_ = nullptr;
164
165 public:
166 /** Destructor
167
168 If this is not empty, shared ownership
169 of the pointee is released. If this was
170 the last reference, the object is
171 returned to the original recycle bin.
172
173 @par Effects
174 @code
175 this->release();
176 @endcode
177 */
178 ~recycled_ptr();
179
180 /** Constructor
181
182 Upon construction, this acquires
183 exclusive access to an object of type
184 `T` which is either recycled from the
185 specified bin, or newly allocated.
186 The object is in an unknown but
187 valid state.
188
189 @par Example
190 @code
191 static recycled< std::string > bin;
192
193 recycled_ptr< std::string > ps( bin );
194
195 // Put the string into a known state
196 ps->clear();
197 @endcode
198
199 @par Postconditions
200 @code
201 &this->bin() == &bin && ! this->empty()
202 @endcode
203
204 @param bin The recycle bin to use
205
206 @see
207 @ref recycled.
208 */
209 explicit
210 recycled_ptr(recycled<T>& bin);
211
212 /** Constructor
213
214 After construction, this is empty and
215 refers to the specified recycle bin.
216
217 @par Example
218 @code
219 static recycled< std::string > bin;
220
221 recycled_ptr< std::string > ps( bin, nullptr );
222
223 // Acquire a string and put it into a known state
224 ps->acquire();
225 ps->clear();
226 @endcode
227
228 @par Postconditions
229 @code
230 &this->bin() == &bin && this->empty()
231 @endcode
232
233 @par Exception Safety
234 Throws nothing.
235
236 @param bin The recycle bin to use
237
238 @see
239 @ref acquire,
240 @ref recycled,
241 @ref release.
242 */
243 recycled_ptr(
244 recycled<T>& bin,
245 std::nullptr_t) noexcept;
246
247 /** Constructor
248
249 Upon construction, this acquires
250 exclusive access to an object of type
251 `T` which is either recycled from a
252 global recycle bin, or newly allocated.
253 The object is in an unknown but
254 valid state.
255
256 @par Example
257 @code
258 recycled_ptr< std::string > ps;
259
260 // Put the string into a known state
261 ps->clear();
262 @endcode
263
264 @par Postconditions
265 @code
266 &this->bin() != nullptr && ! this->empty()
267 @endcode
268
269 @see
270 @ref recycled.
271 */
272 recycled_ptr();
273
274 /** Constructor
275
276 After construction, this is empty
277 and refers to a global recycle bin.
278
279 @par Example
280 @code
281 recycled_ptr< std::string > ps( nullptr );
282
283 // Acquire a string and put it into a known state
284 ps->acquire();
285 ps->clear();
286 @endcode
287
288 @par Postconditions
289 @code
290 &this->bin() != nullptr && this->empty()
291 @endcode
292
293 @par Exception Safety
294 Throws nothing.
295
296 @see
297 @ref acquire,
298 @ref recycled,
299 @ref release.
300 */
301 recycled_ptr(
302 std::nullptr_t) noexcept;
303
304 /** Constructor
305
306 If `other` references an object, the
307 newly constructed pointer acquires
308 shared ownership. Otherwise this is
309 empty. The new pointer references
310 the same recycle bin as `other`.
311
312 @par Postconditions
313 @code
314 &this->bin() == &other->bin() && this->get() == other.get()
315 @endcode
316
317 @par Exception Safety
318 Throws nothing.
319
320 @param other The pointer to copy
321 */
322 recycled_ptr(
323 recycled_ptr const& other) noexcept;
324
325 /** Constructor
326
327 If `other` references an object,
328 ownership is transferred including
329 a reference to the recycle bin. After
330 the move, the moved-from object is empty.
331
332 @par Postconditions
333 @code
334 &this->bin() == &other->bin() && ! this->empty() && other.empty()
335 @endcode
336
337 @par Exception Safety
338 Throws nothing.
339
340 @param other The pointer to move from
341 */
342 recycled_ptr(
343 recycled_ptr&& other) noexcept;
344
345 /** Assignment
346
347 If `other` references an object,
348 ownership is transferred including
349 a reference to the recycle bin. After
350 the move, the moved-from object is empty.
351
352 @par Effects
353 @code
354 this->release()
355 @endcode
356
357 @par Postconditions
358 @code
359 &this->bin() == &other->bin()
360 @endcode
361
362 @par Exception Safety
363 Throws nothing.
364
365 @param other The pointer to move from
366 */
367 recycled_ptr&
368 operator=(
369 recycled_ptr&& other) noexcept;
370
371 /** Assignment
372
373 If `other` references an object,
374 this acquires shared ownership and
375 references the same recycle bin as
376 `other`. The previous object if any
377 is released.
378
379 @par Effects
380 @code
381 this->release()
382 @endcode
383
384 @par Postconditions
385 @code
386 &this->bin() == &other->bin() && this->get() == other.get()
387 @endcode
388
389 @par Exception Safety
390 Throws nothing.
391
392 @param other The pointer to copy from
393 */
394 recycled_ptr&
395 operator=(
396 recycled_ptr const& other) noexcept;
397
398 /** Return true if this does not reference an object
399
400 @par Exception Safety
401 Throws nothing.
402 */
403 bool
404 empty() const noexcept
405 {
406 return p_ == nullptr;
407 }
408
409 /** Return true if this references an object
410
411 @par Effects
412 @code
413 return ! this->empty();
414 @endcode
415
416 @par Exception Safety
417 Throws nothing.
418 */
419 explicit
420 24 operator bool() const noexcept
421 {
422 24 return p_ != nullptr;
423 }
424
425 /** Return the referenced recycle bin
426
427 @par Exception Safety
428 Throws nothing.
429 */
430 recycled<T>&
431 bin() const noexcept
432 {
433 return *bin_;
434 }
435
436 /** Return the referenced object
437
438 If this is empty, `nullptr` is returned.
439
440 @par Exception Safety
441 Throws nothing.
442 */
443 47 T* get() const noexcept
444 {
445 47 return &p_->t;
446 }
447
448 /** Return the referenced object
449
450 If this is empty, `nullptr` is returned.
451
452 @par Exception Safety
453 Throws nothing.
454 */
455 25 T* operator->() const noexcept
456 {
457 25 return get();
458 }
459
460 /** Return the referenced object
461
462 @par Preconditions
463 @code
464 not this->empty()
465 @endcode
466 */
467 T& operator*() const noexcept
468 {
469 return *get();
470 }
471
472 /** Return the referenced object
473
474 If this references an object, it is
475 returned. Otherwise, exclusive ownership
476 of a new object of type `T` is acquired
477 and returned.
478
479 @par Postconditions
480 @code
481 not this->empty()
482 @endcode
483 */
484 T& acquire();
485
486 /** Release the referenced object
487
488 If this references an object, it is
489 released to the referenced recycle bin.
490 The pointer continues to reference
491 the same recycle bin.
492
493 @par Postconditions
494 @code
495 this->empty()
496 @endcode
497
498 @par Exception Safety
499 Throws nothing.
500 */
501 void release() noexcept;
502 };
503
504 } // grammar
505 } // urls
506 } // boost
507
508 #include <boost/url/grammar/impl/recycled.hpp>
509
510 #endif
511