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 |
|
52 |
T* get() const noexcept |
444 |
|
|
{ |
445 |
|
52 |
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 |
|
30 |
T* operator->() const noexcept |
456 |
|
|
{ |
457 |
|
30 |
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 |
|
|
|