shared_ptr.hpp
Go to the documentation of this file.
00001 #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
00002 #define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
00003 
00004 //
00005 //  shared_ptr.hpp
00006 //
00007 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
00008 //  Copyright (c) 2001-2008 Peter Dimov
00009 //
00010 //  Distributed under the Boost Software License, Version 1.0. (See
00011 //  accompanying file LICENSE_1_0.txt or copy at
00012 //  http://www.boost.org/LICENSE_1_0.txt)
00013 //
00014 //  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
00015 //
00016 
00017 #include <boost/config.hpp>   // for broken compiler workarounds
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 // In order to avoid circular dependencies with Boost.TR1
00024 // we make sure that our include of <memory> doesn't try to
00025 // pull in the TR1 headers: that's why we use this header 
00026 // rather than including <memory> directly:
00027 #include <boost/config/no_tr1/memory.hpp>  // std::auto_ptr
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>            // for std::swap
00042 #include <functional>           // for std::less
00043 #include <typeinfo>             // for std::bad_cast
00044 
00045 #if !defined(BOOST_NO_IOSTREAM)
00046 #if !defined(BOOST_NO_IOSFWD)
00047 #include <iosfwd>               // for std::basic_ostream
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 // enable_shared_from_this support
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 // Avoid C4793, ... causes native code generation
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 // rvalue auto_ptr support based on a technique by Dave Abrahams
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 } // namespace detail
00149 
00150 
00151 //
00152 //  shared_ptr
00153 //
00154 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
00155 //  The object pointed to is deleted when the last shared_ptr pointing to it
00156 //  is destroyed or reset.
00157 //
00158 
00159 template<class T> class shared_ptr
00160 {
00161 private:
00162 
00163     // Borland 5.5.1 specific workaround
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() // never throws in 1.30+
00174     {
00175     }
00176 
00177     template<class Y>
00178     explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
00179     {
00180         boost::detail::sp_enable_shared_from_this( this, p, p );
00181     }
00182 
00183     //
00184     // Requirements: D's copy constructor must not throw
00185     //
00186     // shared_ptr will release p by calling d(p)
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     // As above, but with allocator. A's copy constructor shall not throw.
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 //  generated copy constructor, destructor are fine
00202 
00203     template<class Y>
00204     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
00205     {
00206         // it is now safe to copy r.px, as pn(r.pn) did not throw
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() ) // never throws
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 ) // never throws
00230     {
00231     }
00232 
00233     // aliasing
00234     template< class Y >
00235     shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
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) // need to allocate new counter -- the cast failed
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     // assignment
00293 
00294     shared_ptr & operator=( shared_ptr const & r ) // never throws
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) // never throws
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 // Move support
00335 
00336 #if defined( BOOST_HAS_RVALUE_REFS )
00337 
00338     shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
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() // never throws
00355     {
00356         pn.swap( r.pn );
00357         r.px = 0;
00358     }
00359 
00360     shared_ptr & operator=( shared_ptr && r ) // never throws
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 ) // never throws
00368     {
00369         this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
00370         return *this;
00371     }
00372 
00373 #endif
00374 
00375     void reset() // never throws in 1.30+
00376     {
00377         this_type().swap(*this);
00378     }
00379 
00380     template<class Y> void reset(Y * p) // Y must be complete
00381     {
00382         BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
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 // never throws
00402     {
00403         BOOST_ASSERT(px != 0);
00404         return *px;
00405     }
00406 
00407     T * operator-> () const // never throws
00408     {
00409         BOOST_ASSERT(px != 0);
00410         return px;
00411     }
00412 
00413     T * get() const // never throws
00414     {
00415         return px;
00416     }
00417 
00418 // implicit conversion to "bool"
00419 #include <boost/smart_ptr/detail/operator_bool.hpp>
00420 
00421     bool unique() const // never throws
00422     {
00423         return pn.unique();
00424     }
00425 
00426     long use_count() const // never throws
00427     {
00428         return pn.use_count();
00429     }
00430 
00431     void swap(shared_ptr<T> & other) // never throws
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 // Tasteless as this may seem, making all members public allows member templates
00453 // to work in the absence of member template friends. (Matthew Langston)
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;                     // contained pointer
00466     boost::detail::shared_count pn;    // reference counter
00467 
00468 };  // shared_ptr
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 // Resolve the ambiguity between our op!= and the one in rel_ops
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 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
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 // get_pointer() enables boost::mem_fn to recognize shared_ptr
00540 
00541 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
00542 {
00543     return p.get();
00544 }
00545 
00546 // operator<<
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 // in STLport's no-iostreams mode no iostream symbols can be used
00561 #ifndef _STLP_NO_IOSTREAMS
00562 
00563 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
00564 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
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 // get_deleter
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 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
00588 // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
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 // atomic access
00606 
00607 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
00608 
00609 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ )
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 /*mo*/ )
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 /*mo*/ )
00632 {
00633     atomic_store( p, r ); // std::move( 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; // return std::move( r )
00645 }
00646 
00647 template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
00648 {
00649     return atomic_exchange( p, r ); // std::move( 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 /*success*/, memory_order /*failure*/ )
00678 {
00679     return atomic_compare_exchange( p, v, w ); // std::move( w )
00680 }
00681 
00682 #endif
00683 
00684 } // namespace boost
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


appl
Author(s): petercai
autogenerated on Tue Jan 7 2014 11:02:29