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