Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:53:28

0001 //
0002 // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/url
0008 //
0009 
0010 #ifndef BOOST_URL_GRAMMAR_RECYCLED_HPP
0011 #define BOOST_URL_GRAMMAR_RECYCLED_HPP
0012 
0013 #include <boost/url/detail/config.hpp>
0014 #include <boost/url/grammar/detail/recycled.hpp>
0015 #include <atomic>
0016 #include <cstddef>
0017 #include <type_traits>
0018 #include <stddef.h> // ::max_align_t
0019 
0020 #if !defined(BOOST_URL_DISABLE_THREADS)
0021 # include <mutex>
0022 #endif
0023 
0024 namespace boost {
0025 namespace urls {
0026 namespace grammar {
0027 
0028 /** Provides an aligned storage buffer aligned for T
0029 */
0030 #ifdef BOOST_URL_DOCS
0031 template<class T>
0032 struct aligned_storage
0033 {
0034     /** Return a pointer to the aligned storage area
0035     */
0036     void* addr() noexcept;
0037 
0038     /** Return a pointer to the aligned storage area
0039     */
0040     void const* addr() const noexcept;
0041 };
0042 #else
0043 template<class T>
0044 using aligned_storage =
0045     detail::aligned_storage_impl<
0046         detail::nearest_pow2(sizeof(T), 64),
0047             (alignof(::max_align_t) > alignof(T)) ?
0048                 alignof(::max_align_t) : alignof(T)>;
0049 #endif
0050 
0051 //------------------------------------------------
0052 
0053 /** A thread-safe collection of instances of T
0054 
0055     Instances of this type may be used to control
0056     where recycled instances of T come from when
0057     used with @ref recycled_ptr.
0058 
0059     @par Example
0060     @code
0061     static recycled< std::string > bin;
0062 
0063     recycled_ptr< std::string > ps( bin );
0064 
0065     // Put the string into a known state
0066     ps->clear();
0067     @endcode
0068 
0069     @see
0070         @ref recycled_ptr.
0071 */
0072 template<class T>
0073 class recycled
0074 {
0075 public:
0076     /** Destructor
0077 
0078         All recycled instances of T are destroyed.
0079         Undefined behavior results if there are
0080         any @ref recycled_ptr which reference
0081         this recycle bin.
0082     */
0083     ~recycled();
0084 
0085     /** Constructor
0086     */
0087     constexpr recycled() = default;
0088 
0089 private:
0090     template<class>
0091     friend class recycled_ptr;
0092 
0093     struct U
0094     {
0095         T t;
0096         U* next = nullptr;
0097 
0098 #if !defined(BOOST_URL_DISABLE_THREADS)
0099         std::atomic<
0100             std::size_t> refs;
0101 #else
0102         std::size_t refs;
0103 #endif
0104 
0105 
0106         U()
0107             : refs{1}
0108         {
0109         }
0110     };
0111 
0112     struct report;
0113 
0114     U* acquire();
0115     void release(U* u) noexcept;
0116 
0117     U* head_ = nullptr;
0118 
0119 #if !defined(BOOST_URL_DISABLE_THREADS)
0120     std::mutex m_;
0121 #endif
0122 };
0123 
0124 //------------------------------------------------
0125 
0126 /** A pointer to shared instance of T
0127 
0128     This is a smart pointer container which can
0129     acquire shared ownership of an instance of
0130     `T` upon or after construction. The instance
0131     is guaranteed to be in a valid, but unknown
0132     state. Every recycled pointer references
0133     a valid recycle bin.
0134 
0135     @par Example
0136     @code
0137     static recycled< std::string > bin;
0138 
0139     recycled_ptr< std::string > ps( bin );
0140 
0141     // Put the string into a known state
0142     ps->clear();
0143     @endcode
0144 
0145     @tparam T the type of object to
0146         acquire, which must be
0147         <em>DefaultConstructible</em>.
0148 */
0149 template<class T>
0150 class recycled_ptr
0151 {
0152     // T must be default constructible!
0153     static_assert(
0154         std::is_default_constructible<T>::value,
0155         "T must be DefaultConstructible");
0156 
0157     friend class recycled<T>;
0158 
0159     using B = recycled<T>;
0160     using U = typename B::U;
0161 
0162     B* bin_ = nullptr;
0163     U* p_ = nullptr;
0164 
0165 public:
0166     /** Destructor
0167 
0168         If this is not empty, shared ownership
0169         of the pointee is released. If this was
0170         the last reference, the object is
0171         returned to the original recycle bin.
0172 
0173         @par Effects
0174         @code
0175         this->release();
0176         @endcode
0177     */
0178     ~recycled_ptr();
0179 
0180     /** Constructor
0181 
0182         Upon construction, this acquires
0183         exclusive access to an object of type
0184         `T` which is either recycled from the
0185         specified bin, or newly allocated.
0186         The object is in an unknown but
0187         valid state.
0188 
0189         @par Example
0190         @code
0191         static recycled< std::string > bin;
0192 
0193         recycled_ptr< std::string > ps( bin );
0194 
0195         // Put the string into a known state
0196         ps->clear();
0197         @endcode
0198 
0199         @par Postconditions
0200         @code
0201         &this->bin() == &bin && ! this->empty()
0202         @endcode
0203 
0204         @param bin The recycle bin to use
0205 
0206         @see
0207             @ref recycled.
0208     */
0209     explicit
0210     recycled_ptr(recycled<T>& bin);
0211 
0212     /** Constructor
0213 
0214         After construction, this is empty and
0215         refers to the specified recycle bin.
0216 
0217         @par Example
0218         @code
0219         static recycled< std::string > bin;
0220 
0221         recycled_ptr< std::string > ps( bin, nullptr );
0222 
0223         // Acquire a string and put it into a known state
0224         ps->acquire();
0225         ps->clear();
0226         @endcode
0227 
0228         @par Postconditions
0229         @code
0230         &this->bin() == &bin && this->empty()
0231         @endcode
0232 
0233         @par Exception Safety
0234         Throws nothing.
0235 
0236         @param bin The recycle bin to use
0237 
0238         @see
0239             @ref acquire,
0240             @ref recycled,
0241             @ref release.
0242     */
0243     recycled_ptr(
0244         recycled<T>& bin,
0245         std::nullptr_t) noexcept;
0246 
0247     /** Constructor
0248 
0249         Upon construction, this acquires
0250         exclusive access to an object of type
0251         `T` which is either recycled from a
0252         global recycle bin, or newly allocated.
0253         The object is in an unknown but
0254         valid state.
0255 
0256         @par Example
0257         @code
0258         recycled_ptr< std::string > ps;
0259 
0260         // Put the string into a known state
0261         ps->clear();
0262         @endcode
0263 
0264         @par Postconditions
0265         @code
0266         &this->bin() != nullptr && ! this->empty()
0267         @endcode
0268 
0269         @see
0270             @ref recycled.
0271     */
0272     recycled_ptr();
0273 
0274     /** Constructor
0275 
0276         After construction, this is empty
0277         and refers to a global recycle bin.
0278 
0279         @par Example
0280         @code
0281         recycled_ptr< std::string > ps( nullptr );
0282 
0283         // Acquire a string and put it into a known state
0284         ps->acquire();
0285         ps->clear();
0286         @endcode
0287 
0288         @par Postconditions
0289         @code
0290         &this->bin() != nullptr && this->empty()
0291         @endcode
0292 
0293         @par Exception Safety
0294         Throws nothing.
0295 
0296         @see
0297             @ref acquire,
0298             @ref recycled,
0299             @ref release.
0300     */
0301     recycled_ptr(
0302         std::nullptr_t) noexcept;
0303 
0304     /** Constructor
0305 
0306         If `other` references an object, the
0307         newly constructed pointer acquires
0308         shared ownership. Otherwise this is
0309         empty. The new pointer references
0310         the same recycle bin as `other`.
0311 
0312         @par Postconditions
0313         @code
0314         &this->bin() == &other->bin() && this->get() == other.get()
0315         @endcode
0316 
0317         @par Exception Safety
0318         Throws nothing.
0319 
0320         @param other The pointer to copy
0321     */
0322     recycled_ptr(
0323         recycled_ptr const& other) noexcept;
0324 
0325     /** Constructor
0326 
0327         If `other` references an object,
0328         ownership is transferred including
0329         a reference to the recycle bin. After
0330         the move, the moved-from object is empty.
0331 
0332         @par Postconditions
0333         @code
0334         &this->bin() == &other->bin() && ! this->empty() && other.empty()
0335         @endcode
0336 
0337         @par Exception Safety
0338         Throws nothing.
0339 
0340         @param other The pointer to move from
0341     */
0342     recycled_ptr(
0343         recycled_ptr&& other) noexcept;
0344 
0345     /** Assignment
0346 
0347         If `other` references an object,
0348         ownership is transferred including
0349         a reference to the recycle bin. After
0350         the move, the moved-from object is empty.
0351 
0352         @par Effects
0353         @code
0354         this->release()
0355         @endcode
0356 
0357         @par Postconditions
0358         @code
0359         &this->bin() == &other->bin()
0360         @endcode
0361 
0362         @par Exception Safety
0363         Throws nothing.
0364 
0365         @param other The pointer to move from
0366     */
0367     recycled_ptr&
0368     operator=(
0369         recycled_ptr&& other) noexcept;
0370 
0371     /** Assignment
0372 
0373         If `other` references an object,
0374         this acquires shared ownership and
0375         references the same recycle bin as
0376         `other`. The previous object if any
0377         is released.
0378 
0379         @par Effects
0380         @code
0381         this->release()
0382         @endcode
0383 
0384         @par Postconditions
0385         @code
0386         &this->bin() == &other->bin() && this->get() == other.get()
0387         @endcode
0388 
0389         @par Exception Safety
0390         Throws nothing.
0391 
0392         @param other The pointer to copy from
0393     */
0394     recycled_ptr&
0395     operator=(
0396         recycled_ptr const& other) noexcept;
0397 
0398     /** Return true if this does not reference an object
0399 
0400         @par Exception Safety
0401         Throws nothing.
0402     */
0403     bool
0404     empty() const noexcept
0405     {
0406         return p_ == nullptr;
0407     }
0408 
0409     /** Return true if this references an object
0410 
0411         @par Effects
0412         @code
0413         return ! this->empty();
0414         @endcode
0415 
0416         @par Exception Safety
0417         Throws nothing.
0418     */
0419     explicit
0420     operator bool() const noexcept
0421     {
0422         return p_ != nullptr;
0423     }
0424 
0425     /** Return the referenced recycle bin
0426 
0427         @par Exception Safety
0428         Throws nothing.
0429     */
0430     recycled<T>&
0431     bin() const noexcept
0432     {
0433         return *bin_;
0434     }
0435 
0436     /** Return the referenced object
0437 
0438         If this is empty, `nullptr` is returned.
0439 
0440         @par Exception Safety
0441         Throws nothing.
0442     */
0443     T* get() const noexcept
0444     {
0445         return &p_->t;
0446     }
0447 
0448     /** Return the referenced object
0449 
0450         If this is empty, `nullptr` is returned.
0451 
0452         @par Exception Safety
0453         Throws nothing.
0454     */
0455     T* operator->() const noexcept
0456     {
0457         return get();
0458     }
0459 
0460     /** Return the referenced object
0461 
0462         @par Preconditions
0463         @code
0464         not this->empty()
0465         @endcode
0466     */
0467     T& operator*() const noexcept
0468     {
0469         return *get();
0470     }
0471 
0472     /** Return the referenced object
0473 
0474         If this references an object, it is
0475         returned. Otherwise, exclusive ownership
0476         of a new object of type `T` is acquired
0477         and returned.
0478 
0479         @par Postconditions
0480         @code
0481         not this->empty()
0482         @endcode
0483     */
0484     T& acquire();
0485 
0486     /** Release the referenced object
0487 
0488         If this references an object, it is
0489         released to the referenced recycle bin.
0490         The pointer continues to reference
0491         the same recycle bin.
0492 
0493         @par Postconditions
0494         @code
0495         this->empty()
0496         @endcode
0497 
0498         @par Exception Safety
0499         Throws nothing.
0500     */
0501     void release() noexcept;
0502 };
0503 
0504 } // grammar
0505 } // urls
0506 } // boost
0507 
0508 #include <boost/url/grammar/impl/recycled.hpp>
0509 
0510 #endif