00001 #ifndef BOOSTER_SMART_PTR_SHARED_PTR_HPP_INCLUDED
00002 #define BOOSTER_SMART_PTR_SHARED_PTR_HPP_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <booster/config.h>
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>
00027 #include <functional>
00028 #include <typeinfo>
00029
00030 #include <iosfwd>
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
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
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 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 template<class T> class shared_ptr
00124 {
00125 private:
00126
00127
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()
00138 {
00139 }
00140
00141 template<class Y>
00142 explicit shared_ptr( Y * p ): px( p ), pn( p )
00143 {
00144 booster::detail::sp_enable_shared_from_this( this, p, p );
00145 }
00146
00147
00148
00149
00150
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
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
00166
00167 template<class Y>
00168 explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn)
00169 {
00170
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() )
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 )
00186 {
00187 }
00188
00189
00190 template< class Y >
00191 shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn )
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)
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
00241
00242 shared_ptr & operator=( shared_ptr const & r )
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)
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
00271
00272 void reset()
00273 {
00274 this_type().swap(*this);
00275 }
00276
00277 template<class Y> void reset(Y * p)
00278 {
00279 assert(p == 0 || p != px);
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
00299 {
00300 assert(px != 0);
00301 return *px;
00302 }
00303
00304 T * operator-> () const
00305 {
00306 assert(px != 0);
00307 return px;
00308 }
00309
00310 T * get() const
00311 {
00312 return px;
00313 }
00314
00315
00316 #include <booster/smart_ptr/operator_bool.h>
00317
00318 bool unique() const
00319 {
00320 return pn.unique();
00321 }
00322
00323 long use_count() const
00324 {
00325 return pn.use_count();
00326 }
00327
00328 void swap(shared_ptr<T> & other)
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
00350
00351
00352 private:
00353
00354 template<class Y> friend class shared_ptr;
00355 template<class Y> friend class weak_ptr;
00356
00357 T * px;
00358 booster::detail::shared_count pn;
00359
00360 };
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
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
00421
00422 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
00423 {
00424 return p.get();
00425 }
00426
00427
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
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 }
00443
00444 #ifdef BOOSTER_MSVC
00445 # pragma warning(pop)
00446 #endif
00447
00448 #endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED