00001 #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
00002 #define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <boost/config.hpp>
00018
00019 #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
00020 #include <boost/smart_ptr/detail/shared_ptr_nmt.hpp>
00021 #else
00022
00023
00024
00025
00026
00027 #include <boost/config/no_tr1/memory.hpp>
00028
00029 #include <boost/assert.hpp>
00030 #include <boost/checked_delete.hpp>
00031 #include <boost/throw_exception.hpp>
00032 #include <boost/smart_ptr/detail/shared_count.hpp>
00033 #include <boost/detail/workaround.hpp>
00034 #include <boost/smart_ptr/detail/sp_convertible.hpp>
00035
00036 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
00037 #include <boost/smart_ptr/detail/spinlock_pool.hpp>
00038 #include <boost/memory_order.hpp>
00039 #endif
00040
00041 #include <algorithm>
00042 #include <functional>
00043 #include <typeinfo>
00044
00045 #if !defined(BOOST_NO_IOSTREAM)
00046 #if !defined(BOOST_NO_IOSFWD)
00047 #include <iosfwd>
00048 #else
00049 #include <ostream>
00050 #endif
00051 #endif
00052
00053 #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
00054 # pragma warning(push)
00055 # pragma warning(disable:4284) // odd return type for operator->
00056 #endif
00057
00058 namespace boost
00059 {
00060
00061 template<class T> class shared_ptr;
00062 template<class T> class weak_ptr;
00063 template<class T> class enable_shared_from_this;
00064
00065 namespace detail
00066 {
00067
00068 struct static_cast_tag {};
00069 struct const_cast_tag {};
00070 struct dynamic_cast_tag {};
00071 struct polymorphic_cast_tag {};
00072
00073 template<class T> struct shared_ptr_traits
00074 {
00075 typedef T & reference;
00076 };
00077
00078 template<> struct shared_ptr_traits<void>
00079 {
00080 typedef void reference;
00081 };
00082
00083 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
00084
00085 template<> struct shared_ptr_traits<void const>
00086 {
00087 typedef void reference;
00088 };
00089
00090 template<> struct shared_ptr_traits<void volatile>
00091 {
00092 typedef void reference;
00093 };
00094
00095 template<> struct shared_ptr_traits<void const volatile>
00096 {
00097 typedef void reference;
00098 };
00099
00100 #endif
00101
00102
00103
00104 template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
00105 {
00106 if( pe != 0 )
00107 {
00108 pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
00109 }
00110 }
00111
00112 #ifdef _MANAGED
00113
00114
00115
00116 struct sp_any_pointer
00117 {
00118 template<class T> sp_any_pointer( T* ) {}
00119 };
00120
00121 inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
00122 {
00123 }
00124
00125 #else // _MANAGED
00126
00127 inline void sp_enable_shared_from_this( ... )
00128 {
00129 }
00130
00131 #endif // _MANAGED
00132
00133 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
00134
00135
00136
00137 template< class T, class R > struct sp_enable_if_auto_ptr
00138 {
00139 };
00140
00141 template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
00142 {
00143 typedef R type;
00144 };
00145
00146 #endif
00147
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 template<class T> class shared_ptr
00160 {
00161 private:
00162
00163
00164 typedef shared_ptr<T> this_type;
00165
00166 public:
00167
00168 typedef T element_type;
00169 typedef T value_type;
00170 typedef T * pointer;
00171 typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
00172
00173 shared_ptr(): px(0), pn()
00174 {
00175 }
00176
00177 template<class Y>
00178 explicit shared_ptr( Y * p ): px( p ), pn( p )
00179 {
00180 boost::detail::sp_enable_shared_from_this( this, p, p );
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
00190 {
00191 boost::detail::sp_enable_shared_from_this( this, p, p );
00192 }
00193
00194
00195
00196 template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
00197 {
00198 boost::detail::sp_enable_shared_from_this( this, p, p );
00199 }
00200
00201
00202
00203 template<class Y>
00204 explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn)
00205 {
00206
00207 px = r.px;
00208 }
00209
00210 template<class Y>
00211 shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
00212 {
00213 if( !pn.empty() )
00214 {
00215 px = r.px;
00216 }
00217 }
00218
00219 template<class Y>
00220 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
00221
00222 shared_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
00223
00224 #else
00225
00226 shared_ptr( shared_ptr<Y> const & r )
00227
00228 #endif
00229 : px( r.px ), pn( r.pn )
00230 {
00231 }
00232
00233
00234 template< class Y >
00235 shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn )
00236 {
00237 }
00238
00239 template<class Y>
00240 shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
00241 {
00242 }
00243
00244 template<class Y>
00245 shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
00246 {
00247 }
00248
00249 template<class Y>
00250 shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
00251 {
00252 if(px == 0)
00253 {
00254 pn = boost::detail::shared_count();
00255 }
00256 }
00257
00258 template<class Y>
00259 shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
00260 {
00261 if(px == 0)
00262 {
00263 boost::throw_exception(std::bad_cast());
00264 }
00265 }
00266
00267 #ifndef BOOST_NO_AUTO_PTR
00268
00269 template<class Y>
00270 explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
00271 {
00272 Y * tmp = r.get();
00273 pn = boost::detail::shared_count(r);
00274 boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
00275 }
00276
00277 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
00278
00279 template<class Ap>
00280 explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
00281 {
00282 typename Ap::element_type * tmp = r.get();
00283 pn = boost::detail::shared_count( r );
00284 boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
00285 }
00286
00287
00288 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00289
00290 #endif // BOOST_NO_AUTO_PTR
00291
00292
00293
00294 shared_ptr & operator=( shared_ptr const & r )
00295 {
00296 this_type(r).swap(*this);
00297 return *this;
00298 }
00299
00300 #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
00301
00302 template<class Y>
00303 shared_ptr & operator=(shared_ptr<Y> const & r)
00304 {
00305 this_type(r).swap(*this);
00306 return *this;
00307 }
00308
00309 #endif
00310
00311 #ifndef BOOST_NO_AUTO_PTR
00312
00313 template<class Y>
00314 shared_ptr & operator=( std::auto_ptr<Y> & r )
00315 {
00316 this_type(r).swap(*this);
00317 return *this;
00318 }
00319
00320 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
00321
00322 template<class Ap>
00323 typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
00324 {
00325 this_type( r ).swap( *this );
00326 return *this;
00327 }
00328
00329
00330 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00331
00332 #endif // BOOST_NO_AUTO_PTR
00333
00334
00335
00336 #if defined( BOOST_HAS_RVALUE_REFS )
00337
00338 shared_ptr( shared_ptr && r ): px( r.px ), pn()
00339 {
00340 pn.swap( r.pn );
00341 r.px = 0;
00342 }
00343
00344 template<class Y>
00345 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
00346
00347 shared_ptr( shared_ptr<Y> && r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
00348
00349 #else
00350
00351 shared_ptr( shared_ptr<Y> && r )
00352
00353 #endif
00354 : px( r.px ), pn()
00355 {
00356 pn.swap( r.pn );
00357 r.px = 0;
00358 }
00359
00360 shared_ptr & operator=( shared_ptr && r )
00361 {
00362 this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
00363 return *this;
00364 }
00365
00366 template<class Y>
00367 shared_ptr & operator=( shared_ptr<Y> && r )
00368 {
00369 this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
00370 return *this;
00371 }
00372
00373 #endif
00374
00375 void reset()
00376 {
00377 this_type().swap(*this);
00378 }
00379
00380 template<class Y> void reset(Y * p)
00381 {
00382 BOOST_ASSERT(p == 0 || p != px);
00383 this_type(p).swap(*this);
00384 }
00385
00386 template<class Y, class D> void reset( Y * p, D d )
00387 {
00388 this_type( p, d ).swap( *this );
00389 }
00390
00391 template<class Y, class D, class A> void reset( Y * p, D d, A a )
00392 {
00393 this_type( p, d, a ).swap( *this );
00394 }
00395
00396 template<class Y> void reset( shared_ptr<Y> const & r, T * p )
00397 {
00398 this_type( r, p ).swap( *this );
00399 }
00400
00401 reference operator* () const
00402 {
00403 BOOST_ASSERT(px != 0);
00404 return *px;
00405 }
00406
00407 T * operator-> () const
00408 {
00409 BOOST_ASSERT(px != 0);
00410 return px;
00411 }
00412
00413 T * get() const
00414 {
00415 return px;
00416 }
00417
00418
00419 #include <boost/smart_ptr/detail/operator_bool.hpp>
00420
00421 bool unique() const
00422 {
00423 return pn.unique();
00424 }
00425
00426 long use_count() const
00427 {
00428 return pn.use_count();
00429 }
00430
00431 void swap(shared_ptr<T> & other)
00432 {
00433 std::swap(px, other.px);
00434 pn.swap(other.pn);
00435 }
00436
00437 template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
00438 {
00439 return pn < rhs.pn;
00440 }
00441
00442 void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
00443 {
00444 return pn.get_deleter( ti );
00445 }
00446
00447 bool _internal_equiv( shared_ptr const & r ) const
00448 {
00449 return px == r.px && pn == r.pn;
00450 }
00451
00452
00453
00454
00455 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00456
00457 private:
00458
00459 template<class Y> friend class shared_ptr;
00460 template<class Y> friend class weak_ptr;
00461
00462
00463 #endif
00464
00465 T * px;
00466 boost::detail::shared_count pn;
00467
00468 };
00469
00470 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
00471 {
00472 return a.get() == b.get();
00473 }
00474
00475 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
00476 {
00477 return a.get() != b.get();
00478 }
00479
00480 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
00481
00482
00483
00484 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
00485 {
00486 return a.get() != b.get();
00487 }
00488
00489 #endif
00490
00491 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
00492 {
00493 return a._internal_less(b);
00494 }
00495
00496 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
00497 {
00498 a.swap(b);
00499 }
00500
00501 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
00502 {
00503 return shared_ptr<T>(r, boost::detail::static_cast_tag());
00504 }
00505
00506 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
00507 {
00508 return shared_ptr<T>(r, boost::detail::const_cast_tag());
00509 }
00510
00511 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
00512 {
00513 return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
00514 }
00515
00516
00517
00518 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
00519 {
00520 return shared_ptr<T>(r, boost::detail::static_cast_tag());
00521 }
00522
00523 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
00524 {
00525 return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
00526 }
00527
00528 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
00529 {
00530 return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());
00531 }
00532
00533 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
00534 {
00535 BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
00536 return shared_static_cast<T>(r);
00537 }
00538
00539
00540
00541 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
00542 {
00543 return p.get();
00544 }
00545
00546
00547
00548 #if !defined(BOOST_NO_IOSTREAM)
00549
00550 #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
00551
00552 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
00553 {
00554 os << p.get();
00555 return os;
00556 }
00557
00558 #else
00559
00560
00561 #ifndef _STLP_NO_IOSTREAMS
00562
00563 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
00564
00565 using std::basic_ostream;
00566 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
00567 # else
00568 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
00569 # endif
00570 {
00571 os << p.get();
00572 return os;
00573 }
00574
00575 #endif // _STLP_NO_IOSTREAMS
00576
00577 #endif // __GNUC__ < 3
00578
00579 #endif // !defined(BOOST_NO_IOSTREAM)
00580
00581
00582
00583 #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
00584 ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
00585 ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
00586
00587
00588
00589
00590 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
00591 {
00592 void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
00593 return const_cast<D *>(static_cast<D const *>(q));
00594 }
00595
00596 #else
00597
00598 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
00599 {
00600 return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
00601 }
00602
00603 #endif
00604
00605
00606
00607 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
00608
00609 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * )
00610 {
00611 return false;
00612 }
00613
00614 template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
00615 {
00616 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
00617 return *p;
00618 }
00619
00620 template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order )
00621 {
00622 return atomic_load( p );
00623 }
00624
00625 template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
00626 {
00627 boost::detail::spinlock_pool<2>::scoped_lock lock( p );
00628 p->swap( r );
00629 }
00630
00631 template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order )
00632 {
00633 atomic_store( p, r );
00634 }
00635
00636 template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
00637 {
00638 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
00639
00640 sp.lock();
00641 p->swap( r );
00642 sp.unlock();
00643
00644 return r;
00645 }
00646
00647 template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order )
00648 {
00649 return atomic_exchange( p, r );
00650 }
00651
00652 template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
00653 {
00654 boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
00655
00656 sp.lock();
00657
00658 if( p->_internal_equiv( *v ) )
00659 {
00660 p->swap( w );
00661
00662 sp.unlock();
00663
00664 return true;
00665 }
00666 else
00667 {
00668 shared_ptr<T> tmp( *p );
00669
00670 sp.unlock();
00671
00672 tmp.swap( *v );
00673 return false;
00674 }
00675 }
00676
00677 template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order , memory_order )
00678 {
00679 return atomic_compare_exchange( p, v, w );
00680 }
00681
00682 #endif
00683
00684 }
00685
00686 #ifdef BOOST_MSVC
00687 # pragma warning(pop)
00688 #endif
00689
00690 #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
00691
00692 #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED