Chris@16
|
1 #ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED
|
Chris@16
|
2 #define BOOST_SHARED_PTR_132_HPP_INCLUDED
|
Chris@16
|
3
|
Chris@16
|
4 //
|
Chris@16
|
5 // shared_ptr.hpp
|
Chris@16
|
6 //
|
Chris@16
|
7 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
Chris@16
|
8 // Copyright (c) 2001, 2002, 2003 Peter Dimov
|
Chris@16
|
9 //
|
Chris@16
|
10 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
11 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
12 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
13 //
|
Chris@16
|
14 // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
|
Chris@16
|
15 //
|
Chris@16
|
16
|
Chris@16
|
17 #include <boost/config.hpp> // for broken compiler workarounds
|
Chris@16
|
18
|
Chris@16
|
19 #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
Chris@16
|
20 #include <boost/serialization/detail/shared_ptr_nmt_132.hpp>
|
Chris@16
|
21 #else
|
Chris@16
|
22
|
Chris@16
|
23 #include <boost/assert.hpp>
|
Chris@16
|
24 #include <boost/checked_delete.hpp>
|
Chris@16
|
25 #include <boost/serialization/throw_exception.hpp>
|
Chris@16
|
26 #include <boost/detail/workaround.hpp>
|
Chris@16
|
27
|
Chris@16
|
28 #include <boost/serialization/access.hpp>
|
Chris@16
|
29 #include <boost/serialization/detail/shared_count_132.hpp>
|
Chris@16
|
30
|
Chris@16
|
31 #include <memory> // for std::auto_ptr
|
Chris@16
|
32 #include <algorithm> // for std::swap
|
Chris@16
|
33 #include <functional> // for std::less
|
Chris@16
|
34 #include <typeinfo> // for std::bad_cast
|
Chris@16
|
35 #include <iosfwd> // for std::basic_ostream
|
Chris@16
|
36
|
Chris@16
|
37 #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
Chris@16
|
38 # pragma warning(push)
|
Chris@16
|
39 # pragma warning(disable:4284) // odd return type for operator->
|
Chris@16
|
40 #endif
|
Chris@16
|
41
|
Chris@16
|
42 namespace boost_132 {
|
Chris@16
|
43
|
Chris@16
|
44 template<class T> class weak_ptr;
|
Chris@16
|
45 template<class T> class enable_shared_from_this;
|
Chris@16
|
46
|
Chris@16
|
47 namespace detail
|
Chris@16
|
48 {
|
Chris@16
|
49
|
Chris@16
|
50 struct static_cast_tag {};
|
Chris@16
|
51 struct const_cast_tag {};
|
Chris@16
|
52 struct dynamic_cast_tag {};
|
Chris@16
|
53 struct polymorphic_cast_tag {};
|
Chris@16
|
54
|
Chris@16
|
55 template<class T> struct shared_ptr_traits
|
Chris@16
|
56 {
|
Chris@16
|
57 typedef T & reference;
|
Chris@16
|
58 };
|
Chris@16
|
59
|
Chris@16
|
60 template<> struct shared_ptr_traits<void>
|
Chris@16
|
61 {
|
Chris@16
|
62 typedef void reference;
|
Chris@16
|
63 };
|
Chris@16
|
64
|
Chris@16
|
65 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
|
Chris@16
|
66
|
Chris@16
|
67 template<> struct shared_ptr_traits<void const>
|
Chris@16
|
68 {
|
Chris@16
|
69 typedef void reference;
|
Chris@16
|
70 };
|
Chris@16
|
71
|
Chris@16
|
72 template<> struct shared_ptr_traits<void volatile>
|
Chris@16
|
73 {
|
Chris@16
|
74 typedef void reference;
|
Chris@16
|
75 };
|
Chris@16
|
76
|
Chris@16
|
77 template<> struct shared_ptr_traits<void const volatile>
|
Chris@16
|
78 {
|
Chris@16
|
79 typedef void reference;
|
Chris@16
|
80 };
|
Chris@16
|
81
|
Chris@16
|
82 #endif
|
Chris@16
|
83
|
Chris@16
|
84 // enable_shared_from_this support
|
Chris@16
|
85
|
Chris@16
|
86 template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, enable_shared_from_this< T > const * pe, Y const * px )
|
Chris@16
|
87 {
|
Chris@16
|
88 if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
|
Chris@16
|
92 {
|
Chris@16
|
93 }
|
Chris@16
|
94
|
Chris@16
|
95 } // namespace detail
|
Chris@16
|
96
|
Chris@16
|
97
|
Chris@16
|
98 //
|
Chris@16
|
99 // shared_ptr
|
Chris@16
|
100 //
|
Chris@16
|
101 // An enhanced relative of scoped_ptr with reference counted copy semantics.
|
Chris@16
|
102 // The object pointed to is deleted when the last shared_ptr pointing to it
|
Chris@16
|
103 // is destroyed or reset.
|
Chris@16
|
104 //
|
Chris@16
|
105
|
Chris@16
|
106 template<class T> class shared_ptr
|
Chris@16
|
107 {
|
Chris@16
|
108 private:
|
Chris@16
|
109 // Borland 5.5.1 specific workaround
|
Chris@16
|
110 typedef shared_ptr< T > this_type;
|
Chris@16
|
111
|
Chris@16
|
112 public:
|
Chris@16
|
113
|
Chris@16
|
114 typedef T element_type;
|
Chris@16
|
115 typedef T value_type;
|
Chris@16
|
116 typedef T * pointer;
|
Chris@101
|
117 typedef typename detail::shared_ptr_traits< T >::reference reference;
|
Chris@16
|
118
|
Chris@16
|
119 shared_ptr(): px(0), pn() // never throws in 1.30+
|
Chris@16
|
120 {
|
Chris@16
|
121 }
|
Chris@16
|
122
|
Chris@16
|
123 #if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x564) )
|
Chris@16
|
124 template<class Y>
|
Chris@16
|
125 explicit shared_ptr(Y * p): px(p), pn(p, boost::checked_deleter<Y>()) // Y must be complete
|
Chris@16
|
126 #else
|
Chris@16
|
127 template<class Y>
|
Chris@16
|
128 explicit shared_ptr(Y * p): px(p), pn(p, boost::checked_deleter<Y>()) // Y must be complete
|
Chris@16
|
129 #endif
|
Chris@16
|
130 {
|
Chris@16
|
131 detail::sp_enable_shared_from_this( pn, p, p );
|
Chris@16
|
132 }
|
Chris@16
|
133
|
Chris@16
|
134 //
|
Chris@16
|
135 // Requirements: D's copy constructor must not throw
|
Chris@16
|
136 //
|
Chris@16
|
137 // shared_ptr will release p by calling d(p)
|
Chris@16
|
138 //
|
Chris@16
|
139
|
Chris@16
|
140 template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
|
Chris@16
|
141 {
|
Chris@16
|
142 detail::sp_enable_shared_from_this( pn, p, p );
|
Chris@16
|
143 }
|
Chris@16
|
144
|
Chris@16
|
145 // generated copy constructor, assignment, destructor are fine...
|
Chris@16
|
146
|
Chris@16
|
147 // except that Borland C++ has a bug, and g++ with -Wsynth warns
|
Chris@16
|
148 #if defined(__BORLANDC__) || defined(__GNUC__)
|
Chris@16
|
149
|
Chris@16
|
150 shared_ptr & operator=(shared_ptr const & r) // never throws
|
Chris@16
|
151 {
|
Chris@16
|
152 px = r.px;
|
Chris@16
|
153 pn = r.pn; // shared_count::op= doesn't throw
|
Chris@16
|
154 return *this;
|
Chris@16
|
155 }
|
Chris@16
|
156
|
Chris@16
|
157 #endif
|
Chris@16
|
158
|
Chris@16
|
159 template<class Y>
|
Chris@16
|
160 explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
|
Chris@16
|
161 {
|
Chris@16
|
162 // it is now safe to copy r.px, as pn(r.pn) did not throw
|
Chris@16
|
163 px = r.px;
|
Chris@16
|
164 }
|
Chris@16
|
165
|
Chris@16
|
166 template<class Y>
|
Chris@16
|
167 shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
|
Chris@16
|
168 {
|
Chris@16
|
169 }
|
Chris@16
|
170
|
Chris@16
|
171 template<class Y>
|
Chris@16
|
172 shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
Chris@16
|
173 {
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 template<class Y>
|
Chris@16
|
177 shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
|
Chris@16
|
178 {
|
Chris@16
|
179 }
|
Chris@16
|
180
|
Chris@16
|
181 template<class Y>
|
Chris@16
|
182 shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
Chris@16
|
183 {
|
Chris@16
|
184 if(px == 0) // need to allocate new counter -- the cast failed
|
Chris@16
|
185 {
|
Chris@16
|
186 pn = detail::shared_count();
|
Chris@16
|
187 }
|
Chris@16
|
188 }
|
Chris@16
|
189
|
Chris@16
|
190 template<class Y>
|
Chris@16
|
191 shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
Chris@16
|
192 {
|
Chris@16
|
193 if(px == 0)
|
Chris@16
|
194 {
|
Chris@16
|
195 boost::serialization::throw_exception(std::bad_cast());
|
Chris@16
|
196 }
|
Chris@16
|
197 }
|
Chris@16
|
198
|
Chris@16
|
199 #ifndef BOOST_NO_AUTO_PTR
|
Chris@16
|
200
|
Chris@16
|
201 template<class Y>
|
Chris@16
|
202 explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
|
Chris@16
|
203 {
|
Chris@16
|
204 Y * tmp = r.get();
|
Chris@16
|
205 pn = detail::shared_count(r);
|
Chris@16
|
206 detail::sp_enable_shared_from_this( pn, tmp, tmp );
|
Chris@16
|
207 }
|
Chris@16
|
208
|
Chris@16
|
209 #endif
|
Chris@16
|
210
|
Chris@16
|
211 #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
|
Chris@16
|
212
|
Chris@16
|
213 template<class Y>
|
Chris@16
|
214 shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
Chris@16
|
215 {
|
Chris@16
|
216 px = r.px;
|
Chris@16
|
217 pn = r.pn; // shared_count::op= doesn't throw
|
Chris@16
|
218 return *this;
|
Chris@16
|
219 }
|
Chris@16
|
220
|
Chris@16
|
221 #endif
|
Chris@16
|
222
|
Chris@16
|
223 #ifndef BOOST_NO_AUTO_PTR
|
Chris@16
|
224
|
Chris@16
|
225 template<class Y>
|
Chris@16
|
226 shared_ptr & operator=(std::auto_ptr<Y> & r)
|
Chris@16
|
227 {
|
Chris@16
|
228 this_type(r).swap(*this);
|
Chris@16
|
229 return *this;
|
Chris@16
|
230 }
|
Chris@16
|
231
|
Chris@16
|
232 #endif
|
Chris@16
|
233
|
Chris@16
|
234 void reset() // never throws in 1.30+
|
Chris@16
|
235 {
|
Chris@16
|
236 this_type().swap(*this);
|
Chris@16
|
237 }
|
Chris@16
|
238
|
Chris@16
|
239 template<class Y> void reset(Y * p) // Y must be complete
|
Chris@16
|
240 {
|
Chris@16
|
241 BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
|
Chris@16
|
242 this_type(p).swap(*this);
|
Chris@16
|
243 }
|
Chris@16
|
244
|
Chris@16
|
245 template<class Y, class D> void reset(Y * p, D d)
|
Chris@16
|
246 {
|
Chris@16
|
247 this_type(p, d).swap(*this);
|
Chris@16
|
248 }
|
Chris@16
|
249
|
Chris@16
|
250 reference operator* () const // never throws
|
Chris@16
|
251 {
|
Chris@16
|
252 BOOST_ASSERT(px != 0);
|
Chris@16
|
253 return *px;
|
Chris@16
|
254 }
|
Chris@16
|
255
|
Chris@16
|
256 T * operator-> () const // never throws
|
Chris@16
|
257 {
|
Chris@16
|
258 BOOST_ASSERT(px != 0);
|
Chris@16
|
259 return px;
|
Chris@16
|
260 }
|
Chris@16
|
261
|
Chris@16
|
262 T * get() const // never throws
|
Chris@16
|
263 {
|
Chris@16
|
264 return px;
|
Chris@16
|
265 }
|
Chris@16
|
266
|
Chris@16
|
267 // implicit conversion to "bool"
|
Chris@16
|
268
|
Chris@16
|
269 #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
|
Chris@16
|
270
|
Chris@16
|
271 operator bool () const
|
Chris@16
|
272 {
|
Chris@16
|
273 return px != 0;
|
Chris@16
|
274 }
|
Chris@16
|
275
|
Chris@16
|
276 #elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
|
Chris@16
|
277 typedef T * (this_type::*unspecified_bool_type)() const;
|
Chris@16
|
278
|
Chris@16
|
279 operator unspecified_bool_type() const // never throws
|
Chris@16
|
280 {
|
Chris@16
|
281 return px == 0? 0: &this_type::get;
|
Chris@16
|
282 }
|
Chris@16
|
283
|
Chris@16
|
284 #else
|
Chris@16
|
285
|
Chris@16
|
286 typedef T * this_type::*unspecified_bool_type;
|
Chris@16
|
287
|
Chris@16
|
288 operator unspecified_bool_type() const // never throws
|
Chris@16
|
289 {
|
Chris@16
|
290 return px == 0? 0: &this_type::px;
|
Chris@16
|
291 }
|
Chris@16
|
292
|
Chris@16
|
293 #endif
|
Chris@16
|
294
|
Chris@16
|
295 // operator! is redundant, but some compilers need it
|
Chris@16
|
296
|
Chris@16
|
297 bool operator! () const // never throws
|
Chris@16
|
298 {
|
Chris@16
|
299 return px == 0;
|
Chris@16
|
300 }
|
Chris@16
|
301
|
Chris@16
|
302 bool unique() const // never throws
|
Chris@16
|
303 {
|
Chris@16
|
304 return pn.unique();
|
Chris@16
|
305 }
|
Chris@16
|
306
|
Chris@16
|
307 long use_count() const // never throws
|
Chris@16
|
308 {
|
Chris@16
|
309 return pn.use_count();
|
Chris@16
|
310 }
|
Chris@16
|
311
|
Chris@16
|
312 void swap(shared_ptr< T > & other) // never throws
|
Chris@16
|
313 {
|
Chris@16
|
314 std::swap(px, other.px);
|
Chris@16
|
315 pn.swap(other.pn);
|
Chris@16
|
316 }
|
Chris@16
|
317
|
Chris@16
|
318 template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
|
Chris@16
|
319 {
|
Chris@16
|
320 return pn < rhs.pn;
|
Chris@16
|
321 }
|
Chris@16
|
322
|
Chris@16
|
323 void * _internal_get_deleter(std::type_info const & ti) const
|
Chris@16
|
324 {
|
Chris@16
|
325 return pn.get_deleter(ti);
|
Chris@16
|
326 }
|
Chris@16
|
327
|
Chris@16
|
328 // Tasteless as this may seem, making all members public allows member templates
|
Chris@16
|
329 // to work in the absence of member template friends. (Matthew Langston)
|
Chris@16
|
330
|
Chris@16
|
331 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
Chris@16
|
332
|
Chris@16
|
333 private:
|
Chris@16
|
334
|
Chris@16
|
335 template<class Y> friend class shared_ptr;
|
Chris@16
|
336 template<class Y> friend class weak_ptr;
|
Chris@16
|
337
|
Chris@16
|
338
|
Chris@16
|
339 #endif
|
Chris@16
|
340 public: // for serialization
|
Chris@16
|
341 T * px; // contained pointer
|
Chris@16
|
342 detail::shared_count pn; // reference counter
|
Chris@16
|
343
|
Chris@16
|
344 }; // shared_ptr
|
Chris@16
|
345
|
Chris@16
|
346 template<class T, class U> inline bool operator==(shared_ptr< T > const & a, shared_ptr<U> const & b)
|
Chris@16
|
347 {
|
Chris@16
|
348 return a.get() == b.get();
|
Chris@16
|
349 }
|
Chris@16
|
350
|
Chris@16
|
351 template<class T, class U> inline bool operator!=(shared_ptr< T > const & a, shared_ptr<U> const & b)
|
Chris@16
|
352 {
|
Chris@16
|
353 return a.get() != b.get();
|
Chris@16
|
354 }
|
Chris@16
|
355
|
Chris@16
|
356 template<class T, class U> inline bool operator<(shared_ptr< T > const & a, shared_ptr<U> const & b)
|
Chris@16
|
357 {
|
Chris@16
|
358 return a._internal_less(b);
|
Chris@16
|
359 }
|
Chris@16
|
360
|
Chris@16
|
361 template<class T> inline void swap(shared_ptr< T > & a, shared_ptr< T > & b)
|
Chris@16
|
362 {
|
Chris@16
|
363 a.swap(b);
|
Chris@16
|
364 }
|
Chris@16
|
365
|
Chris@16
|
366 template<class T, class U> shared_ptr< T > static_pointer_cast(shared_ptr<U> const & r)
|
Chris@16
|
367 {
|
Chris@16
|
368 return shared_ptr< T >(r, detail::static_cast_tag());
|
Chris@16
|
369 }
|
Chris@16
|
370
|
Chris@16
|
371 template<class T, class U> shared_ptr< T > const_pointer_cast(shared_ptr<U> const & r)
|
Chris@16
|
372 {
|
Chris@16
|
373 return shared_ptr< T >(r, detail::const_cast_tag());
|
Chris@16
|
374 }
|
Chris@16
|
375
|
Chris@16
|
376 template<class T, class U> shared_ptr< T > dynamic_pointer_cast(shared_ptr<U> const & r)
|
Chris@16
|
377 {
|
Chris@16
|
378 return shared_ptr< T >(r, detail::dynamic_cast_tag());
|
Chris@16
|
379 }
|
Chris@16
|
380
|
Chris@16
|
381 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
|
Chris@16
|
382
|
Chris@16
|
383 template<class T, class U> shared_ptr< T > shared_static_cast(shared_ptr<U> const & r)
|
Chris@16
|
384 {
|
Chris@16
|
385 return shared_ptr< T >(r, detail::static_cast_tag());
|
Chris@16
|
386 }
|
Chris@16
|
387
|
Chris@16
|
388 template<class T, class U> shared_ptr< T > shared_dynamic_cast(shared_ptr<U> const & r)
|
Chris@16
|
389 {
|
Chris@16
|
390 return shared_ptr< T >(r, detail::dynamic_cast_tag());
|
Chris@16
|
391 }
|
Chris@16
|
392
|
Chris@16
|
393 template<class T, class U> shared_ptr< T > shared_polymorphic_cast(shared_ptr<U> const & r)
|
Chris@16
|
394 {
|
Chris@16
|
395 return shared_ptr< T >(r, detail::polymorphic_cast_tag());
|
Chris@16
|
396 }
|
Chris@16
|
397
|
Chris@16
|
398 template<class T, class U> shared_ptr< T > shared_polymorphic_downcast(shared_ptr<U> const & r)
|
Chris@16
|
399 {
|
Chris@16
|
400 BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
|
Chris@16
|
401 return shared_static_cast< T >(r);
|
Chris@16
|
402 }
|
Chris@16
|
403
|
Chris@16
|
404 // get_pointer() enables boost::mem_fn to recognize shared_ptr
|
Chris@16
|
405
|
Chris@16
|
406 template<class T> inline T * get_pointer(shared_ptr< T > const & p)
|
Chris@16
|
407 {
|
Chris@16
|
408 return p.get();
|
Chris@16
|
409 }
|
Chris@16
|
410
|
Chris@16
|
411 // operator<<
|
Chris@16
|
412
|
Chris@16
|
413
|
Chris@101
|
414 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
|
Chris@16
|
415 {
|
Chris@16
|
416 os << p.get();
|
Chris@16
|
417 return os;
|
Chris@16
|
418 }
|
Chris@16
|
419
|
Chris@16
|
420 // get_deleter (experimental)
|
Chris@16
|
421
|
Chris@101
|
422 #if defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238)
|
Chris@16
|
423
|
Chris@16
|
424 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
|
Chris@16
|
425 // apparently EDG 2.38 also doesn't accept it
|
Chris@16
|
426
|
Chris@16
|
427 template<class D, class T> D * get_deleter(shared_ptr< T > const & p)
|
Chris@16
|
428 {
|
Chris@16
|
429 void const * q = p._internal_get_deleter(typeid(D));
|
Chris@16
|
430 return const_cast<D *>(static_cast<D const *>(q));
|
Chris@16
|
431 }
|
Chris@16
|
432
|
Chris@16
|
433 #else
|
Chris@16
|
434
|
Chris@16
|
435 template<class D, class T> D * get_deleter(shared_ptr< T > const & p)
|
Chris@16
|
436 {
|
Chris@16
|
437 return static_cast<D *>(p._internal_get_deleter(typeid(D)));
|
Chris@16
|
438 }
|
Chris@16
|
439
|
Chris@16
|
440 #endif
|
Chris@16
|
441
|
Chris@16
|
442 } // namespace boost
|
Chris@16
|
443
|
Chris@16
|
444 #ifdef BOOST_MSVC
|
Chris@16
|
445 # pragma warning(pop)
|
Chris@16
|
446 #endif
|
Chris@16
|
447
|
Chris@16
|
448 #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
Chris@16
|
449
|
Chris@16
|
450 #endif // #ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED
|