shared_ptr.hpp

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

Generated on Wed Jan 21 15:32:10 2009 for SystemC by  doxygen 1.5.5