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 | |
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 | |
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 | |