CppCMS
|
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