Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 10:08:50

0001 /*
0002  *          Copyright Andrey Semashev 2007 - 2013.
0003  * Distributed under the Boost Software License, Version 1.0.
0004  *    (See accompanying file LICENSE_1_0.txt or copy at
0005  *          http://www.boost.org/LICENSE_1_0.txt)
0006  */
0007 /*!
0008  * \file   intrusive_ref_counter.hpp
0009  * \author Andrey Semashev
0010  * \date   12.03.2009
0011  *
0012  * This header contains a reference counter class for \c intrusive_ptr.
0013  */
0014 
0015 #ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
0016 #define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
0017 
0018 #include <boost/smart_ptr/detail/atomic_count.hpp>
0019 #include <boost/config.hpp>
0020 
0021 #ifdef BOOST_HAS_PRAGMA_ONCE
0022 #pragma once
0023 #endif
0024 
0025 #if defined(_MSC_VER)
0026 #pragma warning(push)
0027 // This is a bogus MSVC warning, which is flagged by friend declarations of intrusive_ptr_add_ref and intrusive_ptr_release in intrusive_ref_counter:
0028 // 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
0029 // Note that there is no inline specifier in the declarations.
0030 #pragma warning(disable: 4396)
0031 #endif
0032 
0033 namespace boost {
0034 
0035 namespace sp_adl_block {
0036 
0037 /*!
0038  * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter
0039  *
0040  * The policy instructs the \c intrusive_ref_counter base class to implement
0041  * a reference counter suitable for single threaded use only. Pointers to the same
0042  * object with this kind of reference counter must not be used by different threads.
0043  */
0044 struct thread_unsafe_counter
0045 {
0046     typedef unsigned int type;
0047 
0048     static unsigned int load(unsigned int const& counter) noexcept
0049     {
0050         return counter;
0051     }
0052 
0053     static void increment(unsigned int& counter) noexcept
0054     {
0055         ++counter;
0056     }
0057 
0058     static unsigned int decrement(unsigned int& counter) noexcept
0059     {
0060         return --counter;
0061     }
0062 };
0063 
0064 /*!
0065  * \brief Thread safe reference counter policy for \c intrusive_ref_counter
0066  *
0067  * The policy instructs the \c intrusive_ref_counter base class to implement
0068  * a thread-safe reference counter, if the target platform supports multithreading.
0069  */
0070 struct thread_safe_counter
0071 {
0072     typedef boost::detail::atomic_count type;
0073 
0074     static unsigned int load(boost::detail::atomic_count const& counter) noexcept
0075     {
0076         return static_cast< unsigned int >(static_cast< long >(counter));
0077     }
0078 
0079     static void increment(boost::detail::atomic_count& counter) noexcept
0080     {
0081         ++counter;
0082     }
0083 
0084     static unsigned int decrement(boost::detail::atomic_count& counter) noexcept
0085     {
0086         return static_cast< unsigned int >(--counter);
0087     }
0088 };
0089 
0090 template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
0091 class intrusive_ref_counter;
0092 
0093 template< typename DerivedT, typename CounterPolicyT >
0094 void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) noexcept;
0095 template< typename DerivedT, typename CounterPolicyT >
0096 void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) noexcept;
0097 
0098 /*!
0099  * \brief A reference counter base class
0100  *
0101  * This base class can be used with user-defined classes to add support
0102  * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT.
0103  * Upon releasing the last \c intrusive_ptr referencing the object
0104  * derived from the \c intrusive_ref_counter class, operator \c delete
0105  * is automatically called on the pointer to the object.
0106  *
0107  * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter.
0108  */
0109 template< typename DerivedT, typename CounterPolicyT >
0110 class intrusive_ref_counter
0111 {
0112 private:
0113     //! Reference counter type
0114     typedef typename CounterPolicyT::type counter_type;
0115     //! Reference counter
0116     mutable counter_type m_ref_counter;
0117 
0118 public:
0119     /*!
0120      * Default constructor
0121      *
0122      * \post <tt>use_count() == 0</tt>
0123      */
0124     intrusive_ref_counter() noexcept : m_ref_counter(0)
0125     {
0126     }
0127 
0128     /*!
0129      * Copy constructor
0130      *
0131      * \post <tt>use_count() == 0</tt>
0132      */
0133     intrusive_ref_counter(intrusive_ref_counter const&) noexcept : m_ref_counter(0)
0134     {
0135     }
0136 
0137     /*!
0138      * Assignment
0139      *
0140      * \post The reference counter is not modified after assignment
0141      */
0142     intrusive_ref_counter& operator= (intrusive_ref_counter const&) noexcept { return *this; }
0143 
0144     /*!
0145      * \return The reference counter
0146      */
0147     unsigned int use_count() const noexcept
0148     {
0149         return CounterPolicyT::load(m_ref_counter);
0150     }
0151 
0152 protected:
0153     /*!
0154      * Destructor
0155      */
0156     BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
0157 
0158     friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) noexcept;
0159     friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) noexcept;
0160 };
0161 
0162 template< typename DerivedT, typename CounterPolicyT >
0163 inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) noexcept
0164 {
0165     CounterPolicyT::increment(p->m_ref_counter);
0166 }
0167 
0168 template< typename DerivedT, typename CounterPolicyT >
0169 inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) noexcept
0170 {
0171     if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
0172         delete static_cast< const DerivedT* >(p);
0173 }
0174 
0175 } // namespace sp_adl_block
0176 
0177 using sp_adl_block::intrusive_ref_counter;
0178 using sp_adl_block::thread_unsafe_counter;
0179 using sp_adl_block::thread_safe_counter;
0180 
0181 } // namespace boost
0182 
0183 #if defined(_MSC_VER)
0184 #pragma warning(pop)
0185 #endif
0186 
0187 #endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_