VirtualBox

source: vbox/trunk/src/libs/boost-1.37.0/boost/shared_ptr.hpp@ 20488

Last change on this file since 20488 was 16204, checked in by vboxsync, 16 years ago

export the boost stuff required for Main

File size: 18.1 KB
Line 
1#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
2#define BOOST_SHARED_PTR_HPP_INCLUDED
3
4//
5// shared_ptr.hpp
6//
7// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8// Copyright (c) 2001-2008 Peter Dimov
9//
10// Distributed under the Boost Software License, Version 1.0. (See
11// accompanying file LICENSE_1_0.txt or copy at
12// http://www.boost.org/LICENSE_1_0.txt)
13//
14// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
15//
16
17#include <boost/config.hpp> // for broken compiler workarounds
18
19#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
20#include <boost/detail/shared_ptr_nmt.hpp>
21#else
22
23// In order to avoid circular dependencies with Boost.TR1
24// we make sure that our include of <memory> doesn't try to
25// pull in the TR1 headers: that's why we use this header
26// rather than including <memory> directly:
27#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
28
29#include <boost/assert.hpp>
30#include <boost/checked_delete.hpp>
31#include <boost/throw_exception.hpp>
32#include <boost/detail/shared_count.hpp>
33#include <boost/detail/workaround.hpp>
34#include <boost/detail/sp_convertible.hpp>
35
36#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
37#include <boost/detail/spinlock_pool.hpp>
38#include <boost/memory_order.hpp>
39#endif
40
41#include <algorithm> // for std::swap
42#include <functional> // for std::less
43#include <typeinfo> // for std::bad_cast
44
45#if !defined(BOOST_NO_IOSTREAM)
46#if !defined(BOOST_NO_IOSFWD)
47#include <iosfwd> // for std::basic_ostream
48#else
49#include <ostream>
50#endif
51#endif
52
53#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
54# pragma warning(push)
55# pragma warning(disable:4284) // odd return type for operator->
56#endif
57
58namespace boost
59{
60
61template<class T> class weak_ptr;
62template<class T> class enable_shared_from_this;
63
64namespace detail
65{
66
67struct static_cast_tag {};
68struct const_cast_tag {};
69struct dynamic_cast_tag {};
70struct polymorphic_cast_tag {};
71
72template<class T> struct shared_ptr_traits
73{
74 typedef T & reference;
75};
76
77template<> struct shared_ptr_traits<void>
78{
79 typedef void reference;
80};
81
82#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
83
84template<> struct shared_ptr_traits<void const>
85{
86 typedef void reference;
87};
88
89template<> struct shared_ptr_traits<void volatile>
90{
91 typedef void reference;
92};
93
94template<> struct shared_ptr_traits<void const volatile>
95{
96 typedef void reference;
97};
98
99#endif
100
101// enable_shared_from_this support
102
103template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this<T> const * pe, Y const * px )
104{
105 if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
106}
107
108#ifdef _MANAGED
109
110// Avoid C4793, ... causes native code generation
111
112struct sp_any_pointer
113{
114 template<class T> sp_any_pointer( T* ) {}
115};
116
117inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer )
118{
119}
120
121#else // _MANAGED
122
123#ifdef sgi
124// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed
125# pragma set woff 3506
126#endif
127
128inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
129{
130}
131
132#ifdef sgi
133# pragma reset woff 3506
134#endif
135
136#endif // _MANAGED
137
138#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
139
140// rvalue auto_ptr support based on a technique by Dave Abrahams
141
142template< class T, class R > struct sp_enable_if_auto_ptr
143{
144};
145
146template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
147{
148 typedef R type;
149};
150
151#endif
152
153} // namespace detail
154
155
156//
157// shared_ptr
158//
159// An enhanced relative of scoped_ptr with reference counted copy semantics.
160// The object pointed to is deleted when the last shared_ptr pointing to it
161// is destroyed or reset.
162//
163
164template<class T> class shared_ptr
165{
166private:
167
168 // Borland 5.5.1 specific workaround
169 typedef shared_ptr<T> this_type;
170
171public:
172
173 typedef T element_type;
174 typedef T value_type;
175 typedef T * pointer;
176 typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
177
178 shared_ptr(): px(0), pn() // never throws in 1.30+
179 {
180 }
181
182 template<class Y>
183 explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
184 {
185 boost::detail::sp_enable_shared_from_this( pn, p, p );
186 }
187
188 //
189 // Requirements: D's copy constructor must not throw
190 //
191 // shared_ptr will release p by calling d(p)
192 //
193
194 template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
195 {
196 boost::detail::sp_enable_shared_from_this( pn, p, p );
197 }
198
199 // As above, but with allocator. A's copy constructor shall not throw.
200
201 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
202 {
203 boost::detail::sp_enable_shared_from_this( pn, p, p );
204 }
205
206// generated copy constructor, assignment, destructor are fine...
207
208// except that Borland C++ has a bug, and g++ with -Wsynth warns
209#if defined(__BORLANDC__) || defined(__GNUC__)
210
211 shared_ptr & operator=(shared_ptr const & r) // never throws
212 {
213 px = r.px;
214 pn = r.pn; // shared_count::op= doesn't throw
215 return *this;
216 }
217
218#endif
219
220 template<class Y>
221 explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
222 {
223 // it is now safe to copy r.px, as pn(r.pn) did not throw
224 px = r.px;
225 }
226
227 template<class Y>
228 shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws
229 {
230 if( !pn.empty() )
231 {
232 px = r.px;
233 }
234 }
235
236 template<class Y>
237#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
238
239 shared_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
240
241#else
242
243 shared_ptr( shared_ptr<Y> const & r )
244
245#endif
246 : px( r.px ), pn( r.pn ) // never throws
247 {
248 }
249
250 // aliasing
251 template< class Y >
252 shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
253 {
254 }
255
256 template<class Y>
257 shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
258 {
259 }
260
261 template<class Y>
262 shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
263 {
264 }
265
266 template<class Y>
267 shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
268 {
269 if(px == 0) // need to allocate new counter -- the cast failed
270 {
271 pn = boost::detail::shared_count();
272 }
273 }
274
275 template<class Y>
276 shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
277 {
278 if(px == 0)
279 {
280 boost::throw_exception(std::bad_cast());
281 }
282 }
283
284#ifndef BOOST_NO_AUTO_PTR
285
286 template<class Y>
287 explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
288 {
289 Y * tmp = r.get();
290 pn = boost::detail::shared_count(r);
291 boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
292 }
293
294#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
295
296 template<class Ap>
297 shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
298 {
299 typename Ap::element_type * tmp = r.get();
300 pn = boost::detail::shared_count( r );
301 boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
302 }
303
304
305#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
306
307#endif // BOOST_NO_AUTO_PTR
308
309#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
310
311 template<class Y>
312 shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
313 {
314 px = r.px;
315 pn = r.pn; // shared_count::op= doesn't throw
316 return *this;
317 }
318
319#endif
320
321#ifndef BOOST_NO_AUTO_PTR
322
323 template<class Y>
324 shared_ptr & operator=( std::auto_ptr<Y> & r )
325 {
326 this_type(r).swap(*this);
327 return *this;
328 }
329
330#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
331
332 template<class Ap>
333 typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
334 {
335 this_type( r ).swap( *this );
336 return *this;
337 }
338
339
340#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
341
342#endif // BOOST_NO_AUTO_PTR
343
344// Move support
345
346#if defined( BOOST_HAS_RVALUE_REFS )
347
348 shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
349 {
350 pn.swap( r.pn );
351 r.px = 0;
352 }
353
354 template<class Y>
355#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
356
357 shared_ptr( shared_ptr<Y> && r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
358
359#else
360
361 shared_ptr( shared_ptr<Y> && r )
362
363#endif
364 : px( r.px ), pn() // never throws
365 {
366 pn.swap( r.pn );
367 r.px = 0;
368 }
369
370 shared_ptr & operator=( shared_ptr && r ) // never throws
371 {
372 this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
373 return *this;
374 }
375
376 template<class Y>
377 shared_ptr & operator=( shared_ptr<Y> && r ) // never throws
378 {
379 this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
380 return *this;
381 }
382
383#endif
384
385 void reset() // never throws in 1.30+
386 {
387 this_type().swap(*this);
388 }
389
390 template<class Y> void reset(Y * p) // Y must be complete
391 {
392 BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
393 this_type(p).swap(*this);
394 }
395
396 template<class Y, class D> void reset( Y * p, D d )
397 {
398 this_type( p, d ).swap( *this );
399 }
400
401 template<class Y, class D, class A> void reset( Y * p, D d, A a )
402 {
403 this_type( p, d, a ).swap( *this );
404 }
405
406 template<class Y> void reset( shared_ptr<Y> const & r, T * p )
407 {
408 this_type( r, p ).swap( *this );
409 }
410
411 reference operator* () const // never throws
412 {
413 BOOST_ASSERT(px != 0);
414 return *px;
415 }
416
417 T * operator-> () const // never throws
418 {
419 BOOST_ASSERT(px != 0);
420 return px;
421 }
422
423 T * get() const // never throws
424 {
425 return px;
426 }
427
428 // implicit conversion to "bool"
429
430#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
431
432 operator bool () const
433 {
434 return px != 0;
435 }
436
437#elif defined( _MANAGED )
438
439 static void unspecified_bool( this_type*** )
440 {
441 }
442
443 typedef void (*unspecified_bool_type)( this_type*** );
444
445 operator unspecified_bool_type() const // never throws
446 {
447 return px == 0? 0: unspecified_bool;
448 }
449
450#elif \
451 ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
452 ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
453 ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
454
455 typedef T * (this_type::*unspecified_bool_type)() const;
456
457 operator unspecified_bool_type() const // never throws
458 {
459 return px == 0? 0: &this_type::get;
460 }
461
462#else
463
464 typedef T * this_type::*unspecified_bool_type;
465
466 operator unspecified_bool_type() const // never throws
467 {
468 return px == 0? 0: &this_type::px;
469 }
470
471#endif
472
473 // operator! is redundant, but some compilers need it
474
475 bool operator! () const // never throws
476 {
477 return px == 0;
478 }
479
480 bool unique() const // never throws
481 {
482 return pn.unique();
483 }
484
485 long use_count() const // never throws
486 {
487 return pn.use_count();
488 }
489
490 void swap(shared_ptr<T> & other) // never throws
491 {
492 std::swap(px, other.px);
493 pn.swap(other.pn);
494 }
495
496 template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
497 {
498 return pn < rhs.pn;
499 }
500
501 void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
502 {
503 return pn.get_deleter( ti );
504 }
505
506 bool _internal_equiv( shared_ptr const & r ) const
507 {
508 return px == r.px && pn == r.pn;
509 }
510
511// Tasteless as this may seem, making all members public allows member templates
512// to work in the absence of member template friends. (Matthew Langston)
513
514#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
515
516private:
517
518 template<class Y> friend class shared_ptr;
519 template<class Y> friend class weak_ptr;
520
521
522#endif
523
524 T * px; // contained pointer
525 boost::detail::shared_count pn; // reference counter
526
527}; // shared_ptr
528
529template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
530{
531 return a.get() == b.get();
532}
533
534template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
535{
536 return a.get() != b.get();
537}
538
539#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
540
541// Resolve the ambiguity between our op!= and the one in rel_ops
542
543template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
544{
545 return a.get() != b.get();
546}
547
548#endif
549
550template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
551{
552 return a._internal_less(b);
553}
554
555template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
556{
557 a.swap(b);
558}
559
560template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
561{
562 return shared_ptr<T>(r, boost::detail::static_cast_tag());
563}
564
565template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
566{
567 return shared_ptr<T>(r, boost::detail::const_cast_tag());
568}
569
570template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
571{
572 return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
573}
574
575// shared_*_cast names are deprecated. Use *_pointer_cast instead.
576
577template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
578{
579 return shared_ptr<T>(r, boost::detail::static_cast_tag());
580}
581
582template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
583{
584 return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
585}
586
587template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
588{
589 return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());
590}
591
592template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
593{
594 BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
595 return shared_static_cast<T>(r);
596}
597
598// get_pointer() enables boost::mem_fn to recognize shared_ptr
599
600template<class T> inline T * get_pointer(shared_ptr<T> const & p)
601{
602 return p.get();
603}
604
605// operator<<
606
607#if !defined(BOOST_NO_IOSTREAM)
608
609#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
610
611template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
612{
613 os << p.get();
614 return os;
615}
616
617#else
618
619// in STLport's no-iostreams mode no iostream symbols can be used
620#ifndef _STLP_NO_IOSTREAMS
621
622# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
623// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
624using std::basic_ostream;
625template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
626# else
627template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
628# endif
629{
630 os << p.get();
631 return os;
632}
633
634#endif // _STLP_NO_IOSTREAMS
635
636#endif // __GNUC__ < 3
637
638#endif // !defined(BOOST_NO_IOSTREAM)
639
640// get_deleter
641
642#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
643 ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
644 ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
645
646// g++ 2.9x doesn't allow static_cast<X const *>(void *)
647// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
648
649template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
650{
651 void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
652 return const_cast<D *>(static_cast<D const *>(q));
653}
654
655#else
656
657template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
658{
659 return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
660}
661
662#endif
663
664// atomic access
665
666#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
667
668template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ )
669{
670 return false;
671}
672
673template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
674{
675 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
676 return *p;
677}
678
679template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order /*mo*/ )
680{
681 return atomic_load( p );
682}
683
684template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
685{
686 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
687 p->swap( r );
688}
689
690template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
691{
692 atomic_store( p, r ); // std::move( r )
693}
694
695template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
696{
697 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
698
699 sp.lock();
700 p->swap( r );
701 sp.unlock();
702
703 return r; // return std::move( r )
704}
705
706template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
707{
708 return atomic_exchange( p, r ); // std::move( r )
709}
710
711template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
712{
713 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
714
715 sp.lock();
716
717 if( p->_internal_equiv( *v ) )
718 {
719 p->swap( w );
720
721 sp.unlock();
722
723 return true;
724 }
725 else
726 {
727 shared_ptr<T> tmp( *p );
728
729 sp.unlock();
730
731 tmp.swap( *v );
732 return false;
733 }
734}
735
736template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order /*success*/, memory_order /*failure*/ )
737{
738 return atomic_compare_exchange( p, v, w ); // std::move( w )
739}
740
741#endif
742
743} // namespace boost
744
745#ifdef BOOST_MSVC
746# pragma warning(pop)
747#endif
748
749#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
750
751#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette