LCOV - code coverage report
Current view: top level - boost/url/grammar - recycled.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 9 9 100.0 %
Date: 2024-02-29 20:02:55 Functions: 11 11 100.0 %

          Line data    Source code
       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           3 :         U()
     107           3 :             : refs{1}
     108             :         {
     109           3 :         }
     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          12 :     operator bool() const noexcept
     421             :     {
     422          12 :         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          25 :     T* get() const noexcept
     444             :     {
     445          25 :         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

Generated by: LCOV version 1.15