CppCMS
booster/shared_ptr.h
00001 #ifndef BOOSTER_SMART_PTR_SHARED_PTR_HPP_INCLUDED
00002 #define BOOSTER_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 <booster/config.h>   // for broken compiler workarounds
00018 
00019 #include <memory>
00020 #include <cassert>
00021 #include <booster/backtrace.h>
00022 #include <booster/checked_delete.h>
00023 #include <booster/smart_ptr/shared_count.h>
00024 #include <booster/smart_ptr/sp_convertible.h>
00025 
00026 #include <algorithm>            // for std::swap
00027 #include <functional>           // for std::less
00028 #include <typeinfo>             // for std::bad_cast
00029 
00030 #include <iosfwd>               // for std::basic_ostream
00031 
00032 #ifdef BOOSTER_MSVC  // moved here to work around VC++ compiler crash
00033 # pragma warning(push)
00034 # pragma warning(disable:4284) // odd return type for operator->
00035 #endif
00036 
00037 namespace booster
00038 {
00039 
00040 template<class T> class shared_ptr;
00041 template<class T> class weak_ptr;
00042 template<class T> class enable_shared_from_this;
00043 template<class T> class enable_shared_from_this2;
00044 
00045 namespace detail
00046 {
00047 
00048 struct static_cast_tag {};
00049 struct const_cast_tag {};
00050 struct dynamic_cast_tag {};
00051 struct polymorphic_cast_tag {};
00052 
00053 template<class T> struct shared_ptr_traits
00054 {
00055     typedef T & reference;
00056 };
00057 
00058 template<> struct shared_ptr_traits<void>
00059 {
00060     typedef void reference;
00061 };
00062 
00063 template<> struct shared_ptr_traits<void const>
00064 {
00065     typedef void reference;
00066 };
00067 
00068 template<> struct shared_ptr_traits<void volatile>
00069 {
00070     typedef void reference;
00071 };
00072 
00073 template<> struct shared_ptr_traits<void const volatile>
00074 {
00075     typedef void reference;
00076 };
00077 
00078 // enable_shared_from_this support
00079 
00080 template< class X, class Y, class T > inline void sp_enable_shared_from_this( booster::shared_ptr<X> const * ppx, Y const * py, booster::enable_shared_from_this< T > const * pe )
00081 {
00082     if( pe != 0 )
00083     {
00084         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
00085     }
00086 }
00087 
00088 template< class X, class Y, class T > inline void sp_enable_shared_from_this( booster::shared_ptr<X> * ppx, Y const * py, booster::enable_shared_from_this2< T > const * pe )
00089 {
00090     if( pe != 0 )
00091     {
00092         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
00093     }
00094 }
00095 
00096 inline void sp_enable_shared_from_this( ... )
00097 {
00098 }
00099 
00100 
00101 // rvalue auto_ptr support based on a technique by Dave Abrahams
00102 
00103 template< class T, class R > struct sp_enable_if_auto_ptr
00104 {
00105 };
00106 
00107 template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
00108 {
00109     typedef R type;
00110 }; 
00111 
00112 } // namespace detail
00113 
00114 
00115 //
00116 //  shared_ptr
00117 //
00118 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
00119 //  The object pointed to is deleted when the last shared_ptr pointing to it
00120 //  is destroyed or reset.
00121 //
00122 
00123 template<class T> class shared_ptr
00124 {
00125 private:
00126 
00127     // Borland 5.5.1 specific workaround
00128     typedef shared_ptr<T> this_type;
00129 
00130 public:
00131 
00132     typedef T element_type;
00133     typedef T value_type;
00134     typedef T * pointer;
00135     typedef typename booster::detail::shared_ptr_traits<T>::reference reference;
00136 
00137     shared_ptr(): px(0), pn() // never throws in 1.30+
00138     {
00139     }
00140 
00141     template<class Y>
00142     explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
00143     {
00144         booster::detail::sp_enable_shared_from_this( this, p, p );
00145     }
00146 
00147     //
00148     // Requirements: D's copy constructor must not throw
00149     //
00150     // shared_ptr will release p by calling d(p)
00151     //
00152 
00153     template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
00154     {
00155         booster::detail::sp_enable_shared_from_this( this, p, p );
00156     }
00157 
00158     // As above, but with allocator. A's copy constructor shall not throw.
00159 
00160     template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
00161     {
00162         booster::detail::sp_enable_shared_from_this( this, p, p );
00163     }
00164 
00165 //  generated copy constructor, destructor are fine
00166 
00167     template<class Y>
00168     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
00169     {
00170         // it is now safe to copy r.px, as pn(r.pn) did not throw
00171         px = r.px;
00172     }
00173 
00174     template<class Y>
00175     shared_ptr( weak_ptr<Y> const & r, booster::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, booster::detail::sp_nothrow_tag() ) // never throws
00176     {
00177         if( !pn.empty() )
00178         {
00179             px = r.px;
00180         }
00181     }
00182 
00183     template<class Y>
00184     shared_ptr( shared_ptr<Y> const & r, typename detail::sp_enable_if_convertible<Y,T>::type = detail::sp_empty() )
00185     : px( r.px ), pn( r.pn ) // never throws
00186     {
00187     }
00188 
00189     // aliasing
00190     template< class Y >
00191     shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
00192     {
00193     }
00194 
00195     template<class Y>
00196     shared_ptr(shared_ptr<Y> const & r, booster::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
00197     {
00198     }
00199 
00200     template<class Y>
00201     shared_ptr(shared_ptr<Y> const & r, booster::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
00202     {
00203     }
00204 
00205     template<class Y>
00206     shared_ptr(shared_ptr<Y> const & r, booster::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
00207     {
00208         if(px == 0) // need to allocate new counter -- the cast failed
00209         {
00210             pn = booster::detail::shared_count();
00211         }
00212     }
00213 
00214     template<class Y>
00215     shared_ptr(shared_ptr<Y> const & r, booster::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
00216     {
00217         if(px == 0)
00218         {
00219             throw booster::bad_cast();
00220         }
00221     }
00222 
00223     template<class Y>
00224     explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
00225     {
00226         Y * tmp = r.get();
00227         pn = booster::detail::shared_count(r);
00228         booster::detail::sp_enable_shared_from_this( this, tmp, tmp );
00229     }
00230 
00231     template<class Ap>
00232     explicit shared_ptr( Ap r, typename booster::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
00233     {
00234         typename Ap::element_type * tmp = r.get();
00235         pn = booster::detail::shared_count( r );
00236         booster::detail::sp_enable_shared_from_this( this, tmp, tmp );
00237     }
00238 
00239 
00240     // assignment
00241 
00242     shared_ptr & operator=( shared_ptr const & r ) // never throws
00243     {
00244         this_type(r).swap(*this);
00245         return *this;
00246     }
00247 
00248     template<class Y>
00249     shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
00250     {
00251         this_type(r).swap(*this);
00252         return *this;
00253     }
00254 
00255 
00256     template<class Y>
00257     shared_ptr & operator=( std::auto_ptr<Y> & r )
00258     {
00259         this_type(r).swap(*this);
00260         return *this;
00261     }
00262 
00263     template<class Ap>
00264     typename booster::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
00265     {
00266         this_type( r ).swap( *this );
00267         return *this;
00268     }
00269 
00270 // Move support
00271 
00272     void reset() // never throws in 1.30+
00273     {
00274         this_type().swap(*this);
00275     }
00276 
00277     template<class Y> void reset(Y * p) // Y must be complete
00278     {
00279         assert(p == 0 || p != px); // catch self-reset errors
00280         this_type(p).swap(*this);
00281     }
00282 
00283     template<class Y, class D> void reset( Y * p, D d )
00284     {
00285         this_type( p, d ).swap( *this );
00286     }
00287 
00288     template<class Y, class D, class A> void reset( Y * p, D d, A a )
00289     {
00290         this_type( p, d, a ).swap( *this );
00291     }
00292 
00293     template<class Y> void reset( shared_ptr<Y> const & r, T * p )
00294     {
00295         this_type( r, p ).swap( *this );
00296     }
00297 
00298     reference operator* () const // never throws
00299     {
00300         assert(px != 0);
00301         return *px;
00302     }
00303 
00304     T * operator-> () const // never throws
00305     {
00306         assert(px != 0);
00307         return px;
00308     }
00309 
00310     T * get() const // never throws
00311     {
00312         return px;
00313     }
00314 
00315 // implicit conversion to "bool"
00316 #include <booster/smart_ptr/operator_bool.h>
00317 
00318     bool unique() const // never throws
00319     {
00320         return pn.unique();
00321     }
00322 
00323     long use_count() const // never throws
00324     {
00325         return pn.use_count();
00326     }
00327 
00328     void swap(shared_ptr<T> & other) // never throws
00329     {
00330         std::swap(px, other.px);
00331         pn.swap(other.pn);
00332     }
00333 
00334     template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
00335     {
00336         return pn < rhs.pn;
00337     }
00338 
00339     void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
00340     {
00341         return pn.get_deleter( ti );
00342     }
00343 
00344     bool _internal_equiv( shared_ptr const & r ) const
00345     {
00346         return px == r.px && pn == r.pn;
00347     }
00348 
00349 // Tasteless as this may seem, making all members public allows member templates
00350 // to work in the absence of member template friends. (Matthew Langston)
00351 
00352 private:
00353 
00354     template<class Y> friend class shared_ptr;
00355     template<class Y> friend class weak_ptr;
00356 
00357     T * px;                     // contained pointer
00358     booster::detail::shared_count pn;    // reference counter
00359 
00360 };  // shared_ptr
00361 
00362 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
00363 {
00364     return a.get() == b.get();
00365 }
00366 
00367 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
00368 {
00369     return a.get() != b.get();
00370 }
00371 
00372 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
00373 {
00374     return a._internal_less(b);
00375 }
00376 
00377 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
00378 {
00379     a.swap(b);
00380 }
00381 
00382 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
00383 {
00384     return shared_ptr<T>(r, booster::detail::static_cast_tag());
00385 }
00386 
00387 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
00388 {
00389     return shared_ptr<T>(r, booster::detail::const_cast_tag());
00390 }
00391 
00392 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
00393 {
00394     return shared_ptr<T>(r, booster::detail::dynamic_cast_tag());
00395 }
00396 
00397 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
00398 
00399 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
00400 {
00401     return shared_ptr<T>(r, booster::detail::static_cast_tag());
00402 }
00403 
00404 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
00405 {
00406     return shared_ptr<T>(r, booster::detail::dynamic_cast_tag());
00407 }
00408 
00409 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
00410 {
00411     return shared_ptr<T>(r, booster::detail::polymorphic_cast_tag());
00412 }
00413 
00414 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
00415 {
00416     assert(dynamic_cast<T *>(r.get()) == r.get());
00417     return shared_static_cast<T>(r);
00418 }
00419 
00420 // get_pointer() enables boost::mem_fn to recognize shared_ptr
00421 
00422 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
00423 {
00424     return p.get();
00425 }
00426 
00427 // operator<<
00428 
00429 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
00430 {
00431     os << p.get();
00432     return os;
00433 }
00434 
00435 // get_deleter
00436 
00437 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
00438 {
00439     return static_cast<D *>(p._internal_get_deleter(BOOSTER_SP_TYPEID(D)));
00440 }
00441 
00442 } // namespace boost
00443 
00444 #ifdef BOOSTER_MSVC
00445 # pragma warning(pop)
00446 #endif
00447 
00448 #endif  // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED