Chris@16
|
1 #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
|
Chris@16
|
2 #define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
|
Chris@16
|
3
|
Chris@16
|
4 //
|
Chris@16
|
5 // intrusive_ptr.hpp
|
Chris@16
|
6 //
|
Chris@16
|
7 // Copyright (c) 2001, 2002 Peter Dimov
|
Chris@16
|
8 //
|
Chris@16
|
9 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
10 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
11 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
12 //
|
Chris@16
|
13 // See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
|
Chris@16
|
14 //
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/config.hpp>
|
Chris@16
|
17
|
Chris@16
|
18 #include <boost/assert.hpp>
|
Chris@16
|
19 #include <boost/detail/workaround.hpp>
|
Chris@16
|
20 #include <boost/smart_ptr/detail/sp_convertible.hpp>
|
Chris@16
|
21 #include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
|
Chris@16
|
22
|
Chris@16
|
23 #include <boost/config/no_tr1/functional.hpp> // for std::less
|
Chris@16
|
24
|
Chris@16
|
25 #if !defined(BOOST_NO_IOSTREAM)
|
Chris@16
|
26 #if !defined(BOOST_NO_IOSFWD)
|
Chris@16
|
27 #include <iosfwd> // for std::basic_ostream
|
Chris@16
|
28 #else
|
Chris@16
|
29 #include <ostream>
|
Chris@16
|
30 #endif
|
Chris@16
|
31 #endif
|
Chris@16
|
32
|
Chris@16
|
33
|
Chris@16
|
34 namespace boost
|
Chris@16
|
35 {
|
Chris@16
|
36
|
Chris@16
|
37 //
|
Chris@16
|
38 // intrusive_ptr
|
Chris@16
|
39 //
|
Chris@16
|
40 // A smart pointer that uses intrusive reference counting.
|
Chris@16
|
41 //
|
Chris@16
|
42 // Relies on unqualified calls to
|
Chris@16
|
43 //
|
Chris@16
|
44 // void intrusive_ptr_add_ref(T * p);
|
Chris@16
|
45 // void intrusive_ptr_release(T * p);
|
Chris@16
|
46 //
|
Chris@16
|
47 // (p != 0)
|
Chris@16
|
48 //
|
Chris@16
|
49 // The object is responsible for destroying itself.
|
Chris@16
|
50 //
|
Chris@16
|
51
|
Chris@16
|
52 template<class T> class intrusive_ptr
|
Chris@16
|
53 {
|
Chris@16
|
54 private:
|
Chris@16
|
55
|
Chris@16
|
56 typedef intrusive_ptr this_type;
|
Chris@16
|
57
|
Chris@16
|
58 public:
|
Chris@16
|
59
|
Chris@16
|
60 typedef T element_type;
|
Chris@16
|
61
|
Chris@16
|
62 intrusive_ptr() BOOST_NOEXCEPT : px( 0 )
|
Chris@16
|
63 {
|
Chris@16
|
64 }
|
Chris@16
|
65
|
Chris@16
|
66 intrusive_ptr( T * p, bool add_ref = true ): px( p )
|
Chris@16
|
67 {
|
Chris@16
|
68 if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
Chris@16
|
72
|
Chris@16
|
73 template<class U>
|
Chris@16
|
74 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
Chris@16
|
75
|
Chris@16
|
76 intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
|
Chris@16
|
77
|
Chris@16
|
78 #else
|
Chris@16
|
79
|
Chris@16
|
80 intrusive_ptr( intrusive_ptr<U> const & rhs )
|
Chris@16
|
81
|
Chris@16
|
82 #endif
|
Chris@16
|
83 : px( rhs.get() )
|
Chris@16
|
84 {
|
Chris@16
|
85 if( px != 0 ) intrusive_ptr_add_ref( px );
|
Chris@16
|
86 }
|
Chris@16
|
87
|
Chris@16
|
88 #endif
|
Chris@16
|
89
|
Chris@16
|
90 intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
|
Chris@16
|
91 {
|
Chris@16
|
92 if( px != 0 ) intrusive_ptr_add_ref( px );
|
Chris@16
|
93 }
|
Chris@16
|
94
|
Chris@16
|
95 ~intrusive_ptr()
|
Chris@16
|
96 {
|
Chris@16
|
97 if( px != 0 ) intrusive_ptr_release( px );
|
Chris@16
|
98 }
|
Chris@16
|
99
|
Chris@16
|
100 #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
Chris@16
|
101
|
Chris@16
|
102 template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
|
Chris@16
|
103 {
|
Chris@16
|
104 this_type(rhs).swap(*this);
|
Chris@16
|
105 return *this;
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 #endif
|
Chris@16
|
109
|
Chris@16
|
110 // Move support
|
Chris@16
|
111
|
Chris@16
|
112 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
Chris@16
|
113
|
Chris@16
|
114 intrusive_ptr(intrusive_ptr && rhs) BOOST_NOEXCEPT : px( rhs.px )
|
Chris@16
|
115 {
|
Chris@16
|
116 rhs.px = 0;
|
Chris@16
|
117 }
|
Chris@16
|
118
|
Chris@16
|
119 intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_NOEXCEPT
|
Chris@16
|
120 {
|
Chris@16
|
121 this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
|
Chris@16
|
122 return *this;
|
Chris@16
|
123 }
|
Chris@16
|
124
|
Chris@16
|
125 #endif
|
Chris@16
|
126
|
Chris@16
|
127 intrusive_ptr & operator=(intrusive_ptr const & rhs)
|
Chris@16
|
128 {
|
Chris@16
|
129 this_type(rhs).swap(*this);
|
Chris@16
|
130 return *this;
|
Chris@16
|
131 }
|
Chris@16
|
132
|
Chris@16
|
133 intrusive_ptr & operator=(T * rhs)
|
Chris@16
|
134 {
|
Chris@16
|
135 this_type(rhs).swap(*this);
|
Chris@16
|
136 return *this;
|
Chris@16
|
137 }
|
Chris@16
|
138
|
Chris@16
|
139 void reset() BOOST_NOEXCEPT
|
Chris@16
|
140 {
|
Chris@16
|
141 this_type().swap( *this );
|
Chris@16
|
142 }
|
Chris@16
|
143
|
Chris@16
|
144 void reset( T * rhs )
|
Chris@16
|
145 {
|
Chris@16
|
146 this_type( rhs ).swap( *this );
|
Chris@16
|
147 }
|
Chris@16
|
148
|
Chris@16
|
149 T * get() const BOOST_NOEXCEPT
|
Chris@16
|
150 {
|
Chris@16
|
151 return px;
|
Chris@16
|
152 }
|
Chris@16
|
153
|
Chris@16
|
154 T & operator*() const
|
Chris@16
|
155 {
|
Chris@16
|
156 BOOST_ASSERT( px != 0 );
|
Chris@16
|
157 return *px;
|
Chris@16
|
158 }
|
Chris@16
|
159
|
Chris@16
|
160 T * operator->() const
|
Chris@16
|
161 {
|
Chris@16
|
162 BOOST_ASSERT( px != 0 );
|
Chris@16
|
163 return px;
|
Chris@16
|
164 }
|
Chris@16
|
165
|
Chris@16
|
166 // implicit conversion to "bool"
|
Chris@16
|
167 #include <boost/smart_ptr/detail/operator_bool.hpp>
|
Chris@16
|
168
|
Chris@16
|
169 void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT
|
Chris@16
|
170 {
|
Chris@16
|
171 T * tmp = px;
|
Chris@16
|
172 px = rhs.px;
|
Chris@16
|
173 rhs.px = tmp;
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 private:
|
Chris@16
|
177
|
Chris@16
|
178 T * px;
|
Chris@16
|
179 };
|
Chris@16
|
180
|
Chris@16
|
181 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
Chris@16
|
182 {
|
Chris@16
|
183 return a.get() == b.get();
|
Chris@16
|
184 }
|
Chris@16
|
185
|
Chris@16
|
186 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
Chris@16
|
187 {
|
Chris@16
|
188 return a.get() != b.get();
|
Chris@16
|
189 }
|
Chris@16
|
190
|
Chris@16
|
191 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
|
Chris@16
|
192 {
|
Chris@16
|
193 return a.get() == b;
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
|
Chris@16
|
197 {
|
Chris@16
|
198 return a.get() != b;
|
Chris@16
|
199 }
|
Chris@16
|
200
|
Chris@16
|
201 template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
|
Chris@16
|
202 {
|
Chris@16
|
203 return a == b.get();
|
Chris@16
|
204 }
|
Chris@16
|
205
|
Chris@16
|
206 template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
|
Chris@16
|
207 {
|
Chris@16
|
208 return a != b.get();
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
|
Chris@16
|
212
|
Chris@16
|
213 // Resolve the ambiguity between our op!= and the one in rel_ops
|
Chris@16
|
214
|
Chris@16
|
215 template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
Chris@16
|
216 {
|
Chris@16
|
217 return a.get() != b.get();
|
Chris@16
|
218 }
|
Chris@16
|
219
|
Chris@16
|
220 #endif
|
Chris@16
|
221
|
Chris@16
|
222 #if !defined( BOOST_NO_CXX11_NULLPTR )
|
Chris@16
|
223
|
Chris@16
|
224 template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
Chris@16
|
225 {
|
Chris@16
|
226 return p.get() == 0;
|
Chris@16
|
227 }
|
Chris@16
|
228
|
Chris@16
|
229 template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
|
Chris@16
|
230 {
|
Chris@16
|
231 return p.get() == 0;
|
Chris@16
|
232 }
|
Chris@16
|
233
|
Chris@16
|
234 template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
Chris@16
|
235 {
|
Chris@16
|
236 return p.get() != 0;
|
Chris@16
|
237 }
|
Chris@16
|
238
|
Chris@16
|
239 template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
|
Chris@16
|
240 {
|
Chris@16
|
241 return p.get() != 0;
|
Chris@16
|
242 }
|
Chris@16
|
243
|
Chris@16
|
244 #endif
|
Chris@16
|
245
|
Chris@16
|
246 template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
Chris@16
|
247 {
|
Chris@16
|
248 return std::less<T *>()(a.get(), b.get());
|
Chris@16
|
249 }
|
Chris@16
|
250
|
Chris@16
|
251 template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
|
Chris@16
|
252 {
|
Chris@16
|
253 lhs.swap(rhs);
|
Chris@16
|
254 }
|
Chris@16
|
255
|
Chris@16
|
256 // mem_fn support
|
Chris@16
|
257
|
Chris@16
|
258 template<class T> T * get_pointer(intrusive_ptr<T> const & p)
|
Chris@16
|
259 {
|
Chris@16
|
260 return p.get();
|
Chris@16
|
261 }
|
Chris@16
|
262
|
Chris@16
|
263 template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
|
Chris@16
|
264 {
|
Chris@16
|
265 return static_cast<T *>(p.get());
|
Chris@16
|
266 }
|
Chris@16
|
267
|
Chris@16
|
268 template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
|
Chris@16
|
269 {
|
Chris@16
|
270 return const_cast<T *>(p.get());
|
Chris@16
|
271 }
|
Chris@16
|
272
|
Chris@16
|
273 template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
|
Chris@16
|
274 {
|
Chris@16
|
275 return dynamic_cast<T *>(p.get());
|
Chris@16
|
276 }
|
Chris@16
|
277
|
Chris@16
|
278 // operator<<
|
Chris@16
|
279
|
Chris@16
|
280 #if !defined(BOOST_NO_IOSTREAM)
|
Chris@16
|
281
|
Chris@16
|
282 #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
|
Chris@16
|
283
|
Chris@16
|
284 template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
|
Chris@16
|
285 {
|
Chris@16
|
286 os << p.get();
|
Chris@16
|
287 return os;
|
Chris@16
|
288 }
|
Chris@16
|
289
|
Chris@16
|
290 #else
|
Chris@16
|
291
|
Chris@16
|
292 // in STLport's no-iostreams mode no iostream symbols can be used
|
Chris@16
|
293 #ifndef _STLP_NO_IOSTREAMS
|
Chris@16
|
294
|
Chris@16
|
295 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
|
Chris@16
|
296 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
|
Chris@16
|
297 using std::basic_ostream;
|
Chris@16
|
298 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
|
Chris@16
|
299 # else
|
Chris@16
|
300 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
|
Chris@16
|
301 # endif
|
Chris@16
|
302 {
|
Chris@16
|
303 os << p.get();
|
Chris@16
|
304 return os;
|
Chris@16
|
305 }
|
Chris@16
|
306
|
Chris@16
|
307 #endif // _STLP_NO_IOSTREAMS
|
Chris@16
|
308
|
Chris@16
|
309 #endif // __GNUC__ < 3
|
Chris@16
|
310
|
Chris@16
|
311 #endif // !defined(BOOST_NO_IOSTREAM)
|
Chris@16
|
312
|
Chris@16
|
313 // hash_value
|
Chris@16
|
314
|
Chris@16
|
315 template< class T > struct hash;
|
Chris@16
|
316
|
Chris@16
|
317 template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p )
|
Chris@16
|
318 {
|
Chris@16
|
319 return boost::hash< T* >()( p.get() );
|
Chris@16
|
320 }
|
Chris@16
|
321
|
Chris@16
|
322 } // namespace boost
|
Chris@16
|
323
|
Chris@16
|
324 #endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
|