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