Chris@16
|
1 /*
|
Chris@16
|
2 * Copyright Andrey Semashev 2007 - 2013.
|
Chris@16
|
3 * Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 * (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 * http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 */
|
Chris@16
|
7 /*!
|
Chris@16
|
8 * \file intrusive_ref_counter.hpp
|
Chris@16
|
9 * \author Andrey Semashev
|
Chris@16
|
10 * \date 12.03.2009
|
Chris@16
|
11 *
|
Chris@16
|
12 * This header contains a reference counter class for \c intrusive_ptr.
|
Chris@16
|
13 */
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
|
Chris@16
|
16 #define BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/config.hpp>
|
Chris@16
|
19 #include <boost/smart_ptr/detail/atomic_count.hpp>
|
Chris@16
|
20
|
Chris@16
|
21 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@16
|
22 #pragma once
|
Chris@16
|
23 #endif
|
Chris@16
|
24
|
Chris@16
|
25 #if defined(_MSC_VER)
|
Chris@16
|
26 #pragma warning(push)
|
Chris@16
|
27 // 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
|
28 // 'name' : the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
|
Chris@16
|
29 // Note that there is no inline specifier in the declarations.
|
Chris@16
|
30 #pragma warning(disable: 4396)
|
Chris@16
|
31 #endif
|
Chris@16
|
32
|
Chris@16
|
33 namespace boost {
|
Chris@16
|
34
|
Chris@16
|
35 namespace sp_adl_block {
|
Chris@16
|
36
|
Chris@16
|
37 /*!
|
Chris@16
|
38 * \brief Thread unsafe reference counter policy for \c intrusive_ref_counter
|
Chris@16
|
39 *
|
Chris@16
|
40 * The policy instructs the \c intrusive_ref_counter base class to implement
|
Chris@16
|
41 * a reference counter suitable for single threaded use only. Pointers to the same
|
Chris@16
|
42 * object with this kind of reference counter must not be used by different threads.
|
Chris@16
|
43 */
|
Chris@16
|
44 struct thread_unsafe_counter
|
Chris@16
|
45 {
|
Chris@16
|
46 typedef unsigned int type;
|
Chris@16
|
47
|
Chris@16
|
48 static unsigned int load(unsigned int const& counter) BOOST_NOEXCEPT
|
Chris@16
|
49 {
|
Chris@16
|
50 return counter;
|
Chris@16
|
51 }
|
Chris@16
|
52
|
Chris@16
|
53 static void increment(unsigned int& counter) BOOST_NOEXCEPT
|
Chris@16
|
54 {
|
Chris@16
|
55 ++counter;
|
Chris@16
|
56 }
|
Chris@16
|
57
|
Chris@16
|
58 static unsigned int decrement(unsigned int& counter) BOOST_NOEXCEPT
|
Chris@16
|
59 {
|
Chris@16
|
60 return --counter;
|
Chris@16
|
61 }
|
Chris@16
|
62 };
|
Chris@16
|
63
|
Chris@16
|
64 /*!
|
Chris@16
|
65 * \brief Thread safe reference counter policy for \c intrusive_ref_counter
|
Chris@16
|
66 *
|
Chris@16
|
67 * The policy instructs the \c intrusive_ref_counter base class to implement
|
Chris@16
|
68 * a thread-safe reference counter, if the target platform supports multithreading.
|
Chris@16
|
69 */
|
Chris@16
|
70 struct thread_safe_counter
|
Chris@16
|
71 {
|
Chris@16
|
72 typedef boost::detail::atomic_count type;
|
Chris@16
|
73
|
Chris@16
|
74 static unsigned int load(boost::detail::atomic_count const& counter) BOOST_NOEXCEPT
|
Chris@16
|
75 {
|
Chris@16
|
76 return static_cast< unsigned int >(static_cast< long >(counter));
|
Chris@16
|
77 }
|
Chris@16
|
78
|
Chris@16
|
79 static void increment(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
|
Chris@16
|
80 {
|
Chris@16
|
81 ++counter;
|
Chris@16
|
82 }
|
Chris@16
|
83
|
Chris@16
|
84 static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
|
Chris@16
|
85 {
|
Chris@16
|
86 return --counter;
|
Chris@16
|
87 }
|
Chris@16
|
88 };
|
Chris@16
|
89
|
Chris@16
|
90 template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
|
Chris@16
|
91 class intrusive_ref_counter;
|
Chris@16
|
92
|
Chris@16
|
93 template< typename DerivedT, typename CounterPolicyT >
|
Chris@16
|
94 void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
Chris@16
|
95 template< typename DerivedT, typename CounterPolicyT >
|
Chris@16
|
96 void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
Chris@16
|
97
|
Chris@16
|
98 /*!
|
Chris@16
|
99 * \brief A reference counter base class
|
Chris@16
|
100 *
|
Chris@16
|
101 * This base class can be used with user-defined classes to add support
|
Chris@16
|
102 * for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT.
|
Chris@16
|
103 * Upon releasing the last \c intrusive_ptr referencing the object
|
Chris@16
|
104 * derived from the \c intrusive_ref_counter class, operator \c delete
|
Chris@16
|
105 * is automatically called on the pointer to the object.
|
Chris@16
|
106 *
|
Chris@16
|
107 * The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter.
|
Chris@16
|
108 */
|
Chris@16
|
109 template< typename DerivedT, typename CounterPolicyT >
|
Chris@16
|
110 class intrusive_ref_counter
|
Chris@16
|
111 {
|
Chris@16
|
112 private:
|
Chris@16
|
113 //! Reference counter type
|
Chris@16
|
114 typedef typename CounterPolicyT::type counter_type;
|
Chris@16
|
115 //! Reference counter
|
Chris@16
|
116 mutable counter_type m_ref_counter;
|
Chris@16
|
117
|
Chris@16
|
118 public:
|
Chris@16
|
119 /*!
|
Chris@16
|
120 * Default constructor
|
Chris@16
|
121 *
|
Chris@16
|
122 * \post <tt>use_count() == 0</tt>
|
Chris@16
|
123 */
|
Chris@16
|
124 intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0)
|
Chris@16
|
125 {
|
Chris@16
|
126 }
|
Chris@16
|
127
|
Chris@16
|
128 /*!
|
Chris@16
|
129 * Copy constructor
|
Chris@16
|
130 *
|
Chris@16
|
131 * \post <tt>use_count() == 0</tt>
|
Chris@16
|
132 */
|
Chris@16
|
133 intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0)
|
Chris@16
|
134 {
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137 /*!
|
Chris@16
|
138 * Assignment
|
Chris@16
|
139 *
|
Chris@16
|
140 * \post The reference counter is not modified after assignment
|
Chris@16
|
141 */
|
Chris@16
|
142 intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; }
|
Chris@16
|
143
|
Chris@16
|
144 /*!
|
Chris@16
|
145 * \return The reference counter
|
Chris@16
|
146 */
|
Chris@16
|
147 unsigned int use_count() const BOOST_NOEXCEPT
|
Chris@16
|
148 {
|
Chris@16
|
149 return CounterPolicyT::load(m_ref_counter);
|
Chris@16
|
150 }
|
Chris@16
|
151
|
Chris@16
|
152 protected:
|
Chris@16
|
153 /*!
|
Chris@16
|
154 * Destructor
|
Chris@16
|
155 */
|
Chris@16
|
156 BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
|
Chris@16
|
157
|
Chris@16
|
158 friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
Chris@16
|
159 friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
Chris@16
|
160 };
|
Chris@16
|
161
|
Chris@16
|
162 template< typename DerivedT, typename CounterPolicyT >
|
Chris@16
|
163 inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
|
Chris@16
|
164 {
|
Chris@16
|
165 CounterPolicyT::increment(p->m_ref_counter);
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168 template< typename DerivedT, typename CounterPolicyT >
|
Chris@16
|
169 inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
|
Chris@16
|
170 {
|
Chris@16
|
171 if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
|
Chris@16
|
172 delete static_cast< const DerivedT* >(p);
|
Chris@16
|
173 }
|
Chris@16
|
174
|
Chris@16
|
175 } // namespace sp_adl_block
|
Chris@16
|
176
|
Chris@16
|
177 using sp_adl_block::intrusive_ref_counter;
|
Chris@16
|
178 using sp_adl_block::thread_unsafe_counter;
|
Chris@16
|
179 using sp_adl_block::thread_safe_counter;
|
Chris@16
|
180
|
Chris@16
|
181 } // namespace boost
|
Chris@16
|
182
|
Chris@16
|
183 #if defined(_MSC_VER)
|
Chris@16
|
184 #pragma warning(pop)
|
Chris@16
|
185 #endif
|
Chris@16
|
186
|
Chris@16
|
187 #endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_
|