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