• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/config/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 
intrusive_ptr()63     BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
64     {
65     }
66 
intrusive_ptr(T * p,bool add_ref=true)67     intrusive_ptr( T * p, bool add_ref = true ): px( p )
68     {
69         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 
intrusive_ptr(intrusive_ptr<U> const & rhs,typename boost::detail::sp_enable_if_convertible<U,T>::type=boost::detail::sp_empty ())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 
intrusive_ptr(intrusive_ptr const & rhs)91     intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
92     {
93         if( px != 0 ) intrusive_ptr_add_ref( px );
94     }
95 
~intrusive_ptr()96     ~intrusive_ptr()
97     {
98         if( px != 0 ) intrusive_ptr_release( px );
99     }
100 
101 #if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
102 
operator =(intrusive_ptr<U> const & rhs)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 
intrusive_ptr(intrusive_ptr && rhs)115     intrusive_ptr(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT : px( rhs.px )
116     {
117         rhs.px = 0;
118     }
119 
operator =(intrusive_ptr && rhs)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 
intrusive_ptr(intrusive_ptr<U> && rhs,typename boost::detail::sp_enable_if_convertible<U,T>::type=boost::detail::sp_empty ())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>
operator =(intrusive_ptr<U> && rhs)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 
operator =(intrusive_ptr const & rhs)152     intrusive_ptr & operator=(intrusive_ptr const & rhs)
153     {
154         this_type(rhs).swap(*this);
155         return *this;
156     }
157 
operator =(T * rhs)158     intrusive_ptr & operator=(T * rhs)
159     {
160         this_type(rhs).swap(*this);
161         return *this;
162     }
163 
reset()164     void reset()
165     {
166         this_type().swap( *this );
167     }
168 
reset(T * rhs)169     void reset( T * rhs )
170     {
171         this_type( rhs ).swap( *this );
172     }
173 
reset(T * rhs,bool add_ref)174     void reset( T * rhs, bool add_ref )
175     {
176         this_type( rhs, add_ref ).swap( *this );
177     }
178 
get() const179     T * get() const BOOST_SP_NOEXCEPT
180     {
181         return px;
182     }
183 
detach()184     T * detach() BOOST_SP_NOEXCEPT
185     {
186         T * ret = px;
187         px = 0;
188         return ret;
189     }
190 
operator *() const191     T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
192     {
193         BOOST_ASSERT( px != 0 );
194         return *px;
195     }
196 
operator ->() const197     T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
198     {
199         BOOST_ASSERT( px != 0 );
200         return px;
201     }
202 
203 // implicit conversion to "bool"
204 #include <boost/smart_ptr/detail/operator_bool.hpp>
205 
swap(intrusive_ptr & rhs)206     void swap(intrusive_ptr & rhs) BOOST_SP_NOEXCEPT
207     {
208         T * tmp = px;
209         px = rhs.px;
210         rhs.px = tmp;
211     }
212 
213 private:
214 
215     T * px;
216 };
217 
operator ==(intrusive_ptr<T> const & a,intrusive_ptr<U> const & b)218 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
219 {
220     return a.get() == b.get();
221 }
222 
operator !=(intrusive_ptr<T> const & a,intrusive_ptr<U> const & b)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 
operator ==(intrusive_ptr<T> const & a,U * b)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 
operator !=(intrusive_ptr<T> const & a,U * b)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 
operator ==(T * a,intrusive_ptr<U> const & b)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 
operator !=(T * a,intrusive_ptr<U> const & b)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 
operator !=(intrusive_ptr<T> const & a,intrusive_ptr<T> const & b)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 
operator ==(intrusive_ptr<T> const & p,boost::detail::sp_nullptr_t)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 
operator ==(boost::detail::sp_nullptr_t,intrusive_ptr<T> const & p)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 
operator !=(intrusive_ptr<T> const & p,boost::detail::sp_nullptr_t)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 
operator !=(boost::detail::sp_nullptr_t,intrusive_ptr<T> const & p)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 
operator <(intrusive_ptr<T> const & a,intrusive_ptr<T> const & b)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 
swap(intrusive_ptr<T> & lhs,intrusive_ptr<T> & rhs)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 
get_pointer(intrusive_ptr<T> const & p)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 
static_pointer_cast(intrusive_ptr<U> const & p)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 
const_pointer_cast(intrusive_ptr<U> const & p)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 
dynamic_pointer_cast(intrusive_ptr<U> const & p)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 
static_pointer_cast(intrusive_ptr<U> && p)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 
const_pointer_cast(intrusive_ptr<U> && p)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 
dynamic_pointer_cast(intrusive_ptr<U> && p)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 
operator <<(std::ostream & os,intrusive_ptr<Y> const & p)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;
operator <<(basic_ostream<E,T> & os,intrusive_ptr<Y> const & p)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 
hash_value(boost::intrusive_ptr<T> const & p)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 // std::hash
389 
390 #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
391 
392 namespace std
393 {
394 
395 template<class T> struct hash< ::boost::intrusive_ptr<T> >
396 {
operator ()std::hash397     std::size_t operator()( ::boost::intrusive_ptr<T> const & p ) const BOOST_SP_NOEXCEPT
398     {
399         return std::hash< T* >()( p.get() );
400     }
401 };
402 
403 } // namespace std
404 
405 #endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
406 
407 #endif  // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
408