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   	    BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
64   	    {
65   	    }
66   	
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   	
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   	
(1) Event exn_spec_violation: An exception of type "std::length_error" is thrown but the throw list "throw()" doesn't allow it to be thrown. This will cause a call to unexpected() which usually calls terminate().
Also see events: [fun_call_w_exception]
96   	    ~intrusive_ptr()
97   	    {
(2) Event fun_call_w_exception: Called function throws an exception of type "std::length_error". [details]
Also see events: [exn_spec_violation]
98   	        if( px != 0 ) intrusive_ptr_release( px );
99   	    }
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  	    intrusive_ptr(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT : px( rhs.px )
116  	    {
117  	        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  	    void reset()
165  	    {
166  	        this_type().swap( *this );
167  	    }
168  	
169  	    void reset( T * rhs )
170  	    {
171  	        this_type( rhs ).swap( *this );
172  	    }
173  	
174  	    void reset( T * rhs, bool add_ref )
175  	    {
176  	        this_type( rhs, add_ref ).swap( *this );
177  	    }
178  	
179  	    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  	    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  	
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  	
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  	
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  	template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
301  	{
302  	    return static_cast<T *>(p.get());
303  	}
304  	
305  	template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
306  	{
307  	    return const_cast<T *>(p.get());
308  	}
309  	
310  	template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
311  	{
312  	    return dynamic_cast<T *>(p.get());
313  	}
314  	
315  	// operator<<
316  	
317  	#if !defined(BOOST_NO_IOSTREAM)
318  	
319  	#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) &&  (__GNUC__ < 3) )
320  	
321  	template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
322  	{
323  	    os << p.get();
324  	    return os;
325  	}
326  	
327  	#else
328  	
329  	// in STLport's no-iostreams mode no iostream symbols can be used
330  	#ifndef _STLP_NO_IOSTREAMS
331  	
332  	# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
333  	// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
334  	using std::basic_ostream;
335  	template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
336  	# else
337  	template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
338  	# endif 
339  	{
340  	    os << p.get();
341  	    return os;
342  	}
343  	
344  	#endif // _STLP_NO_IOSTREAMS
345  	
346  	#endif // __GNUC__ < 3
347  	
348  	#endif // !defined(BOOST_NO_IOSTREAM)
349  	
350  	// hash_value
351  	
352  	template< class T > struct hash;
353  	
354  	template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
355  	{
356  	    return boost::hash< T* >()( p.get() );
357  	}
358  	
359  	} // namespace boost
360  	
361  	#endif  // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
362