2 * Copyright Andrey Semashev 2007 - 2013.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
8 * \file intrusive_ref_counter.hpp
9 * \author Andrey Semashev
12 * This header contains a reference counter class for \c intrusive_ptr.
15 #ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
16 #define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
18 #include <boost/config.hpp>
19 #include <boost/smart_ptr/detail/atomic_count.hpp>
20 #include <boost/smart_ptr/detail/sp_noexcept.hpp>
22 #ifdef BOOST_HAS_PRAGMA_ONCE
28 // 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:
29 // 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
30 // Note that there is no inline specifier in the declarations.
31 #pragma warning(disable: 4396)
36 namespace sp_adl_block {
39 * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter
41 * The policy instructs the \c intrusive_ref_counter base class to implement
42 * a reference counter suitable for single threaded use only. Pointers to the same
43 * object with this kind of reference counter must not be used by different threads.
45 struct thread_unsafe_counter
47 typedef unsigned int type;
49 static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT
54 static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT
59 static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT
66 * \brief Thread safe reference counter policy for \c intrusive_ref_counter
68 * The policy instructs the \c intrusive_ref_counter base class to implement
69 * a thread-safe reference counter, if the target platform supports multithreading.
71 struct thread_safe_counter
73 typedef boost::detail::atomic_count type;
75 static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT
77 return static_cast< unsigned int >(static_cast< long >(counter));
80 static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
85 static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
87 return static_cast< unsigned int >(--counter);
91 template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
92 class intrusive_ref_counter;
94 template< typename DerivedT, typename CounterPolicyT >
95 void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
96 template< typename DerivedT, typename CounterPolicyT >
97 void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
100 * \brief A reference counter base class
102 * This base class can be used with user-defined classes to add support
103 * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT.
104 * Upon releasing the last \c intrusive_ptr referencing the object
105 * derived from the \c intrusive_ref_counter class, operator \c delete
106 * is automatically called on the pointer to the object.
108 * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter.
110 template< typename DerivedT, typename CounterPolicyT >
111 class intrusive_ref_counter
114 //! Reference counter type
115 typedef typename CounterPolicyT::type counter_type;
116 //! Reference counter
117 mutable counter_type m_ref_counter;
121 * Default constructor
123 * \post <tt>use_count() == 0</tt>
125 intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0)
132 * \post <tt>use_count() == 0</tt>
134 intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0)
141 * \post The reference counter is not modified after assignment
143 intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; }
146 * \return The reference counter
148 unsigned int use_count() const BOOST_SP_NOEXCEPT
150 return CounterPolicyT::load(m_ref_counter);
157 BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
159 friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
160 friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
163 template< typename DerivedT, typename CounterPolicyT >
164 inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
166 CounterPolicyT::increment(p->m_ref_counter);
169 template< typename DerivedT, typename CounterPolicyT >
170 inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
172 if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
173 delete static_cast< const DerivedT* >(p);
176 } // namespace sp_adl_block
178 using sp_adl_block::intrusive_ref_counter;
179 using sp_adl_block::thread_unsafe_counter;
180 using sp_adl_block::thread_safe_counter;
184 #if defined(_MSC_VER)
188 #endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_