Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:52:41

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