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@101
|
149 void reset( T * rhs, bool add_ref )
|
Chris@101
|
150 {
|
Chris@101
|
151 this_type( rhs, add_ref ).swap( *this );
|
Chris@101
|
152 }
|
Chris@101
|
153
|
Chris@16
|
154 T * get() const BOOST_NOEXCEPT
|
Chris@16
|
155 {
|
Chris@16
|
156 return px;
|
Chris@16
|
157 }
|
Chris@16
|
158
|
Chris@101
|
159 T * detach() BOOST_NOEXCEPT
|
Chris@101
|
160 {
|
Chris@101
|
161 T * ret = px;
|
Chris@101
|
162 px = 0;
|
Chris@101
|
163 return ret;
|
Chris@101
|
164 }
|
Chris@101
|
165
|
Chris@16
|
166 T & operator*() const
|
Chris@16
|
167 {
|
Chris@16
|
168 BOOST_ASSERT( px != 0 );
|
Chris@16
|
169 return *px;
|
Chris@16
|
170 }
|
Chris@16
|
171
|
Chris@16
|
172 T * operator->() const
|
Chris@16
|
173 {
|
Chris@16
|
174 BOOST_ASSERT( px != 0 );
|
Chris@16
|
175 return px;
|
Chris@16
|
176 }
|
Chris@16
|
177
|
Chris@16
|
178 // implicit conversion to "bool"
|
Chris@16
|
179 #include <boost/smart_ptr/detail/operator_bool.hpp>
|
Chris@16
|
180
|
Chris@16
|
181 void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT
|
Chris@16
|
182 {
|
Chris@16
|
183 T * tmp = px;
|
Chris@16
|
184 px = rhs.px;
|
Chris@16
|
185 rhs.px = tmp;
|
Chris@16
|
186 }
|
Chris@16
|
187
|
Chris@16
|
188 private:
|
Chris@16
|
189
|
Chris@16
|
190 T * px;
|
Chris@16
|
191 };
|
Chris@16
|
192
|
Chris@16
|
193 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
Chris@16
|
194 {
|
Chris@16
|
195 return a.get() == b.get();
|
Chris@16
|
196 }
|
Chris@16
|
197
|
Chris@16
|
198 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
Chris@16
|
199 {
|
Chris@16
|
200 return a.get() != b.get();
|
Chris@16
|
201 }
|
Chris@16
|
202
|
Chris@16
|
203 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
|
Chris@16
|
204 {
|
Chris@16
|
205 return a.get() == b;
|
Chris@16
|
206 }
|
Chris@16
|
207
|
Chris@16
|
208 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
|
Chris@16
|
209 {
|
Chris@16
|
210 return a.get() != b;
|
Chris@16
|
211 }
|
Chris@16
|
212
|
Chris@16
|
213 template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
|
Chris@16
|
214 {
|
Chris@16
|
215 return a == b.get();
|
Chris@16
|
216 }
|
Chris@16
|
217
|
Chris@16
|
218 template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
|
Chris@16
|
219 {
|
Chris@16
|
220 return a != b.get();
|
Chris@16
|
221 }
|
Chris@16
|
222
|
Chris@16
|
223 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
|
Chris@16
|
224
|
Chris@16
|
225 // Resolve the ambiguity between our op!= and the one in rel_ops
|
Chris@16
|
226
|
Chris@16
|
227 template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
Chris@16
|
228 {
|
Chris@16
|
229 return a.get() != b.get();
|
Chris@16
|
230 }
|
Chris@16
|
231
|
Chris@16
|
232 #endif
|
Chris@16
|
233
|
Chris@16
|
234 #if !defined( BOOST_NO_CXX11_NULLPTR )
|
Chris@16
|
235
|
Chris@16
|
236 template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
Chris@16
|
237 {
|
Chris@16
|
238 return p.get() == 0;
|
Chris@16
|
239 }
|
Chris@16
|
240
|
Chris@16
|
241 template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
|
Chris@16
|
242 {
|
Chris@16
|
243 return p.get() == 0;
|
Chris@16
|
244 }
|
Chris@16
|
245
|
Chris@16
|
246 template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
Chris@16
|
247 {
|
Chris@16
|
248 return p.get() != 0;
|
Chris@16
|
249 }
|
Chris@16
|
250
|
Chris@16
|
251 template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
|
Chris@16
|
252 {
|
Chris@16
|
253 return p.get() != 0;
|
Chris@16
|
254 }
|
Chris@16
|
255
|
Chris@16
|
256 #endif
|
Chris@16
|
257
|
Chris@16
|
258 template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
Chris@16
|
259 {
|
Chris@16
|
260 return std::less<T *>()(a.get(), b.get());
|
Chris@16
|
261 }
|
Chris@16
|
262
|
Chris@16
|
263 template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
|
Chris@16
|
264 {
|
Chris@16
|
265 lhs.swap(rhs);
|
Chris@16
|
266 }
|
Chris@16
|
267
|
Chris@16
|
268 // mem_fn support
|
Chris@16
|
269
|
Chris@16
|
270 template<class T> T * get_pointer(intrusive_ptr<T> const & p)
|
Chris@16
|
271 {
|
Chris@16
|
272 return p.get();
|
Chris@16
|
273 }
|
Chris@16
|
274
|
Chris@16
|
275 template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
|
Chris@16
|
276 {
|
Chris@16
|
277 return static_cast<T *>(p.get());
|
Chris@16
|
278 }
|
Chris@16
|
279
|
Chris@16
|
280 template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
|
Chris@16
|
281 {
|
Chris@16
|
282 return const_cast<T *>(p.get());
|
Chris@16
|
283 }
|
Chris@16
|
284
|
Chris@16
|
285 template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
|
Chris@16
|
286 {
|
Chris@16
|
287 return dynamic_cast<T *>(p.get());
|
Chris@16
|
288 }
|
Chris@16
|
289
|
Chris@16
|
290 // operator<<
|
Chris@16
|
291
|
Chris@16
|
292 #if !defined(BOOST_NO_IOSTREAM)
|
Chris@16
|
293
|
Chris@16
|
294 #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
|
Chris@16
|
295
|
Chris@16
|
296 template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
|
Chris@16
|
297 {
|
Chris@16
|
298 os << p.get();
|
Chris@16
|
299 return os;
|
Chris@16
|
300 }
|
Chris@16
|
301
|
Chris@16
|
302 #else
|
Chris@16
|
303
|
Chris@16
|
304 // in STLport's no-iostreams mode no iostream symbols can be used
|
Chris@16
|
305 #ifndef _STLP_NO_IOSTREAMS
|
Chris@16
|
306
|
Chris@16
|
307 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
|
Chris@16
|
308 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
|
Chris@16
|
309 using std::basic_ostream;
|
Chris@16
|
310 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
|
Chris@16
|
311 # else
|
Chris@16
|
312 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
|
313 # endif
|
Chris@16
|
314 {
|
Chris@16
|
315 os << p.get();
|
Chris@16
|
316 return os;
|
Chris@16
|
317 }
|
Chris@16
|
318
|
Chris@16
|
319 #endif // _STLP_NO_IOSTREAMS
|
Chris@16
|
320
|
Chris@16
|
321 #endif // __GNUC__ < 3
|
Chris@16
|
322
|
Chris@16
|
323 #endif // !defined(BOOST_NO_IOSTREAM)
|
Chris@16
|
324
|
Chris@16
|
325 // hash_value
|
Chris@16
|
326
|
Chris@16
|
327 template< class T > struct hash;
|
Chris@16
|
328
|
Chris@16
|
329 template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p )
|
Chris@16
|
330 {
|
Chris@16
|
331 return boost::hash< T* >()( p.get() );
|
Chris@16
|
332 }
|
Chris@16
|
333
|
Chris@16
|
334 } // namespace boost
|
Chris@16
|
335
|
Chris@16
|
336 #endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
|