| /* |
| * Copyright Andrey Semashev 2007 - 2013. |
| * Distributed under the Boost Software License, Version 1.0. |
| * (See accompanying file LICENSE_1_0.txt or copy at |
| * http://www.boost.org/LICENSE_1_0.txt) |
| */ |
| /*! |
| * \file intrusive_ref_counter.hpp |
| * \author Andrey Semashev |
| * \date 12.03.2009 |
| * |
| * This header contains a reference counter class for \c intrusive_ptr. |
| */ |
| |
| #ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ |
| #define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ |
| |
| #include <boost/config.hpp> |
| #include <boost/smart_ptr/detail/atomic_count.hpp> |
| |
| #ifdef BOOST_HAS_PRAGMA_ONCE |
| #pragma once |
| #endif |
| |
| #if defined(_MSC_VER) |
| #pragma warning(push) |
| // 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: |
| // 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template |
| // Note that there is no inline specifier in the declarations. |
| #pragma warning(disable: 4396) |
| #endif |
| |
| namespace boost { |
| |
| namespace sp_adl_block { |
| |
| /*! |
| * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter |
| * |
| * The policy instructs the \c intrusive_ref_counter base class to implement |
| * a reference counter suitable for single threaded use only. Pointers to the same |
| * object with this kind of reference counter must not be used by different threads. |
| */ |
| struct thread_unsafe_counter |
| { |
| typedef unsigned int type; |
| |
| static unsigned int load(unsigned int const& counter) BOOST_NOEXCEPT |
| { |
| return counter; |
| } |
| |
| static void increment(unsigned int& counter) BOOST_NOEXCEPT |
| { |
| ++counter; |
| } |
| |
| static unsigned int decrement(unsigned int& counter) BOOST_NOEXCEPT |
| { |
| return --counter; |
| } |
| }; |
| |
| /*! |
| * \brief Thread safe reference counter policy for \c intrusive_ref_counter |
| * |
| * The policy instructs the \c intrusive_ref_counter base class to implement |
| * a thread-safe reference counter, if the target platform supports multithreading. |
| */ |
| struct thread_safe_counter |
| { |
| typedef boost::detail::atomic_count type; |
| |
| static unsigned int load(boost::detail::atomic_count const& counter) BOOST_NOEXCEPT |
| { |
| return static_cast< unsigned int >(static_cast< long >(counter)); |
| } |
| |
| static void increment(boost::detail::atomic_count& counter) BOOST_NOEXCEPT |
| { |
| ++counter; |
| } |
| |
| static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_NOEXCEPT |
| { |
| return --counter; |
| } |
| }; |
| |
| template< typename DerivedT, typename CounterPolicyT = thread_safe_counter > |
| class intrusive_ref_counter; |
| |
| template< typename DerivedT, typename CounterPolicyT > |
| void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; |
| template< typename DerivedT, typename CounterPolicyT > |
| void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; |
| |
| /*! |
| * \brief A reference counter base class |
| * |
| * This base class can be used with user-defined classes to add support |
| * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT. |
| * Upon releasing the last \c intrusive_ptr referencing the object |
| * derived from the \c intrusive_ref_counter class, operator \c delete |
| * is automatically called on the pointer to the object. |
| * |
| * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter. |
| */ |
| template< typename DerivedT, typename CounterPolicyT > |
| class intrusive_ref_counter |
| { |
| private: |
| //! Reference counter type |
| typedef typename CounterPolicyT::type counter_type; |
| //! Reference counter |
| mutable counter_type m_ref_counter; |
| |
| public: |
| /*! |
| * Default constructor |
| * |
| * \post <tt>use_count() == 0</tt> |
| */ |
| intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0) |
| { |
| } |
| |
| /*! |
| * Copy constructor |
| * |
| * \post <tt>use_count() == 0</tt> |
| */ |
| intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0) |
| { |
| } |
| |
| /*! |
| * Assignment |
| * |
| * \post The reference counter is not modified after assignment |
| */ |
| intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; } |
| |
| /*! |
| * \return The reference counter |
| */ |
| unsigned int use_count() const BOOST_NOEXCEPT |
| { |
| return CounterPolicyT::load(m_ref_counter); |
| } |
| |
| protected: |
| /*! |
| * Destructor |
| */ |
| BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {}) |
| |
| friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; |
| friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; |
| }; |
| |
| template< typename DerivedT, typename CounterPolicyT > |
| inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT |
| { |
| CounterPolicyT::increment(p->m_ref_counter); |
| } |
| |
| template< typename DerivedT, typename CounterPolicyT > |
| inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT |
| { |
| if (CounterPolicyT::decrement(p->m_ref_counter) == 0) |
| delete static_cast< const DerivedT* >(p); |
| } |
| |
| } // namespace sp_adl_block |
| |
| using sp_adl_block::intrusive_ref_counter; |
| using sp_adl_block::thread_unsafe_counter; |
| using sp_adl_block::thread_safe_counter; |
| |
| } // namespace boost |
| |
| #if defined(_MSC_VER) |
| #pragma warning(pop) |
| #endif |
| |
| #endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_ |