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