williamr@2: #ifndef BOOST_SHARED_PTR_HPP_INCLUDED williamr@2: #define BOOST_SHARED_PTR_HPP_INCLUDED williamr@2: williamr@2: // williamr@2: // shared_ptr.hpp williamr@2: // williamr@2: // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. williamr@2: // Copyright (c) 2001-2006 Peter Dimov williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: // williamr@2: // See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. williamr@2: // williamr@2: williamr@2: #include // for broken compiler workarounds williamr@2: williamr@2: #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) williamr@2: #include williamr@2: #else williamr@2: williamr@2: #include // for std::auto_ptr williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #include // for std::swap williamr@2: #include // for std::less williamr@2: #include // for std::bad_cast williamr@2: #include // for std::basic_ostream williamr@2: williamr@2: #ifdef BOOST_MSVC // moved here to work around VC++ compiler crash williamr@2: # pragma warning(push) williamr@2: # pragma warning(disable:4284) // odd return type for operator-> williamr@2: #endif williamr@2: williamr@2: namespace boost williamr@2: { williamr@2: williamr@2: template class weak_ptr; williamr@2: template class enable_shared_from_this; williamr@2: williamr@2: namespace detail williamr@2: { williamr@2: williamr@2: struct static_cast_tag {}; williamr@2: struct const_cast_tag {}; williamr@2: struct dynamic_cast_tag {}; williamr@2: struct polymorphic_cast_tag {}; williamr@2: williamr@2: template struct shared_ptr_traits williamr@2: { williamr@2: typedef T & reference; williamr@2: }; williamr@2: williamr@2: template<> struct shared_ptr_traits williamr@2: { williamr@2: typedef void reference; williamr@2: }; williamr@2: williamr@2: #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS) williamr@2: williamr@2: template<> struct shared_ptr_traits williamr@2: { williamr@2: typedef void reference; williamr@2: }; williamr@2: williamr@2: template<> struct shared_ptr_traits williamr@2: { williamr@2: typedef void reference; williamr@2: }; williamr@2: williamr@2: template<> struct shared_ptr_traits williamr@2: { williamr@2: typedef void reference; williamr@2: }; williamr@2: williamr@2: #endif williamr@2: williamr@2: // enable_shared_from_this support williamr@2: williamr@2: template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) williamr@2: { williamr@2: if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); williamr@2: } williamr@2: williamr@2: #ifdef sgi williamr@2: // Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed williamr@2: # pragma set woff 3506 williamr@2: #endif williamr@2: williamr@2: inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) williamr@2: { williamr@2: } williamr@2: williamr@2: #ifdef sgi williamr@2: # pragma reset woff 3506 williamr@2: #endif williamr@2: williamr@2: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) williamr@2: williamr@2: // rvalue auto_ptr support based on a technique by Dave Abrahams williamr@2: williamr@2: template< class T, class R > struct sp_enable_if_auto_ptr williamr@2: { williamr@2: }; williamr@2: williamr@2: template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > williamr@2: { williamr@2: typedef R type; williamr@2: }; williamr@2: williamr@2: #endif williamr@2: williamr@2: } // namespace detail williamr@2: williamr@2: williamr@2: // williamr@2: // shared_ptr williamr@2: // williamr@2: // An enhanced relative of scoped_ptr with reference counted copy semantics. williamr@2: // The object pointed to is deleted when the last shared_ptr pointing to it williamr@2: // is destroyed or reset. williamr@2: // williamr@2: williamr@2: template class shared_ptr williamr@2: { williamr@2: private: williamr@2: williamr@2: // Borland 5.5.1 specific workaround williamr@2: typedef shared_ptr this_type; williamr@2: williamr@2: public: williamr@2: williamr@2: typedef T element_type; williamr@2: typedef T value_type; williamr@2: typedef T * pointer; williamr@2: typedef typename boost::detail::shared_ptr_traits::reference reference; williamr@2: williamr@2: shared_ptr(): px(0), pn() // never throws in 1.30+ williamr@2: { williamr@2: } williamr@2: williamr@2: template williamr@2: explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete williamr@2: { williamr@2: boost::detail::sp_enable_shared_from_this( pn, p, p ); williamr@2: } williamr@2: williamr@2: // williamr@2: // Requirements: D's copy constructor must not throw williamr@2: // williamr@2: // shared_ptr will release p by calling d(p) williamr@2: // williamr@2: williamr@2: template shared_ptr(Y * p, D d): px(p), pn(p, d) williamr@2: { williamr@2: boost::detail::sp_enable_shared_from_this( pn, p, p ); williamr@2: } williamr@2: williamr@2: // As above, but with allocator. A's copy constructor shall not throw. williamr@2: williamr@2: template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) williamr@2: { williamr@2: boost::detail::sp_enable_shared_from_this( pn, p, p ); williamr@2: } williamr@2: williamr@2: // generated copy constructor, assignment, destructor are fine... williamr@2: williamr@2: // except that Borland C++ has a bug, and g++ with -Wsynth warns williamr@2: #if defined(__BORLANDC__) || defined(__GNUC__) williamr@2: williamr@2: shared_ptr & operator=(shared_ptr const & r) // never throws williamr@2: { williamr@2: px = r.px; williamr@2: pn = r.pn; // shared_count::op= doesn't throw williamr@2: return *this; williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: template williamr@2: explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw williamr@2: { williamr@2: // it is now safe to copy r.px, as pn(r.pn) did not throw williamr@2: px = r.px; williamr@2: } williamr@2: williamr@2: template williamr@2: shared_ptr(shared_ptr const & r): px(r.px), pn(r.pn) // never throws williamr@2: { williamr@2: } williamr@2: williamr@2: template williamr@2: shared_ptr(shared_ptr const & r, boost::detail::static_cast_tag): px(static_cast(r.px)), pn(r.pn) williamr@2: { williamr@2: } williamr@2: williamr@2: template williamr@2: shared_ptr(shared_ptr const & r, boost::detail::const_cast_tag): px(const_cast(r.px)), pn(r.pn) williamr@2: { williamr@2: } williamr@2: williamr@2: template williamr@2: shared_ptr(shared_ptr const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) williamr@2: { williamr@2: if(px == 0) // need to allocate new counter -- the cast failed williamr@2: { williamr@2: pn = boost::detail::shared_count(); williamr@2: } williamr@2: } williamr@2: williamr@2: template williamr@2: shared_ptr(shared_ptr const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast(r.px)), pn(r.pn) williamr@2: { williamr@2: if(px == 0) williamr@2: { williamr@2: boost::throw_exception(std::bad_cast()); williamr@2: } williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_AUTO_PTR williamr@2: williamr@2: template williamr@2: explicit shared_ptr(std::auto_ptr & r): px(r.get()), pn() williamr@2: { williamr@2: Y * tmp = r.get(); williamr@2: pn = boost::detail::shared_count(r); williamr@2: boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); williamr@2: } williamr@2: williamr@2: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) williamr@2: williamr@2: template williamr@2: explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr::type = 0 ): px( r.get() ), pn() williamr@2: { williamr@2: typename Ap::element_type * tmp = r.get(); williamr@2: pn = boost::detail::shared_count( r ); williamr@2: boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); williamr@2: } williamr@2: williamr@2: williamr@2: #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: williamr@2: #endif // BOOST_NO_AUTO_PTR williamr@2: williamr@2: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) williamr@2: williamr@2: template williamr@2: shared_ptr & operator=(shared_ptr const & r) // never throws williamr@2: { williamr@2: px = r.px; williamr@2: pn = r.pn; // shared_count::op= doesn't throw williamr@2: return *this; williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: #ifndef BOOST_NO_AUTO_PTR williamr@2: williamr@2: template williamr@2: shared_ptr & operator=( std::auto_ptr & r ) williamr@2: { williamr@2: this_type(r).swap(*this); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) williamr@2: williamr@2: template williamr@2: typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r ) williamr@2: { williamr@2: this_type( r ).swap( *this ); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: williamr@2: #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: williamr@2: #endif // BOOST_NO_AUTO_PTR williamr@2: williamr@2: void reset() // never throws in 1.30+ williamr@2: { williamr@2: this_type().swap(*this); williamr@2: } williamr@2: williamr@2: template void reset(Y * p) // Y must be complete williamr@2: { williamr@2: BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors williamr@2: this_type(p).swap(*this); williamr@2: } williamr@2: williamr@2: template void reset( Y * p, D d ) williamr@2: { williamr@2: this_type( p, d ).swap( *this ); williamr@2: } williamr@2: williamr@2: template void reset( Y * p, D d, A a ) williamr@2: { williamr@2: this_type( p, d, a ).swap( *this ); williamr@2: } williamr@2: williamr@2: reference operator* () const // never throws williamr@2: { williamr@2: BOOST_ASSERT(px != 0); williamr@2: return *px; williamr@2: } williamr@2: williamr@2: T * operator-> () const // never throws williamr@2: { williamr@2: BOOST_ASSERT(px != 0); williamr@2: return px; williamr@2: } williamr@2: williamr@2: T * get() const // never throws williamr@2: { williamr@2: return px; williamr@2: } williamr@2: williamr@2: // implicit conversion to "bool" williamr@2: williamr@2: #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x580) williamr@2: williamr@2: operator bool () const williamr@2: { williamr@2: return px != 0; williamr@2: } williamr@2: williamr@2: #elif defined( _MANAGED ) williamr@2: williamr@2: static void unspecified_bool( this_type*** ) williamr@2: { williamr@2: } williamr@2: williamr@2: typedef void (*unspecified_bool_type)( this_type*** ); williamr@2: williamr@2: operator unspecified_bool_type() const // never throws williamr@2: { williamr@2: return px == 0? 0: unspecified_bool; williamr@2: } williamr@2: williamr@2: #elif \ williamr@2: ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ williamr@2: ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) williamr@2: williamr@2: typedef T * (this_type::*unspecified_bool_type)() const; williamr@2: williamr@2: operator unspecified_bool_type() const // never throws williamr@2: { williamr@2: return px == 0? 0: &this_type::get; williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: typedef T * this_type::*unspecified_bool_type; williamr@2: williamr@2: operator unspecified_bool_type() const // never throws williamr@2: { williamr@2: return px == 0? 0: &this_type::px; williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: // operator! is redundant, but some compilers need it williamr@2: williamr@2: bool operator! () const // never throws williamr@2: { williamr@2: return px == 0; williamr@2: } williamr@2: williamr@2: bool unique() const // never throws williamr@2: { williamr@2: return pn.unique(); williamr@2: } williamr@2: williamr@2: long use_count() const // never throws williamr@2: { williamr@2: return pn.use_count(); williamr@2: } williamr@2: williamr@2: void swap(shared_ptr & other) // never throws williamr@2: { williamr@2: std::swap(px, other.px); williamr@2: pn.swap(other.pn); williamr@2: } williamr@2: williamr@2: template bool _internal_less(shared_ptr const & rhs) const williamr@2: { williamr@2: return pn < rhs.pn; williamr@2: } williamr@2: williamr@2: void * _internal_get_deleter(std::type_info const & ti) const williamr@2: { williamr@2: return pn.get_deleter(ti); williamr@2: } williamr@2: williamr@2: // Tasteless as this may seem, making all members public allows member templates williamr@2: // to work in the absence of member template friends. (Matthew Langston) williamr@2: williamr@2: #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS williamr@2: williamr@2: private: williamr@2: williamr@2: template friend class shared_ptr; williamr@2: template friend class weak_ptr; williamr@2: williamr@2: williamr@2: #endif williamr@2: williamr@2: T * px; // contained pointer williamr@2: boost::detail::shared_count pn; // reference counter williamr@2: williamr@2: }; // shared_ptr williamr@2: williamr@2: template inline bool operator==(shared_ptr const & a, shared_ptr const & b) williamr@2: { williamr@2: return a.get() == b.get(); williamr@2: } williamr@2: williamr@2: template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) williamr@2: { williamr@2: return a.get() != b.get(); williamr@2: } williamr@2: williamr@2: #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96 williamr@2: williamr@2: // Resolve the ambiguity between our op!= and the one in rel_ops williamr@2: williamr@2: template inline bool operator!=(shared_ptr const & a, shared_ptr const & b) williamr@2: { williamr@2: return a.get() != b.get(); williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: template inline bool operator<(shared_ptr const & a, shared_ptr const & b) williamr@2: { williamr@2: return a._internal_less(b); williamr@2: } williamr@2: williamr@2: template inline void swap(shared_ptr & a, shared_ptr & b) williamr@2: { williamr@2: a.swap(b); williamr@2: } williamr@2: williamr@2: template shared_ptr static_pointer_cast(shared_ptr const & r) williamr@2: { williamr@2: return shared_ptr(r, boost::detail::static_cast_tag()); williamr@2: } williamr@2: williamr@2: template shared_ptr const_pointer_cast(shared_ptr const & r) williamr@2: { williamr@2: return shared_ptr(r, boost::detail::const_cast_tag()); williamr@2: } williamr@2: williamr@2: template shared_ptr dynamic_pointer_cast(shared_ptr const & r) williamr@2: { williamr@2: return shared_ptr(r, boost::detail::dynamic_cast_tag()); williamr@2: } williamr@2: williamr@2: // shared_*_cast names are deprecated. Use *_pointer_cast instead. williamr@2: williamr@2: template shared_ptr shared_static_cast(shared_ptr const & r) williamr@2: { williamr@2: return shared_ptr(r, boost::detail::static_cast_tag()); williamr@2: } williamr@2: williamr@2: template shared_ptr shared_dynamic_cast(shared_ptr const & r) williamr@2: { williamr@2: return shared_ptr(r, boost::detail::dynamic_cast_tag()); williamr@2: } williamr@2: williamr@2: template shared_ptr shared_polymorphic_cast(shared_ptr const & r) williamr@2: { williamr@2: return shared_ptr(r, boost::detail::polymorphic_cast_tag()); williamr@2: } williamr@2: williamr@2: template shared_ptr shared_polymorphic_downcast(shared_ptr const & r) williamr@2: { williamr@2: BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); williamr@2: return shared_static_cast(r); williamr@2: } williamr@2: williamr@2: // get_pointer() enables boost::mem_fn to recognize shared_ptr williamr@2: williamr@2: template inline T * get_pointer(shared_ptr const & p) williamr@2: { williamr@2: return p.get(); williamr@2: } williamr@2: williamr@2: // operator<< williamr@2: williamr@2: #if defined(__GNUC__) && (__GNUC__ < 3) williamr@2: williamr@2: template std::ostream & operator<< (std::ostream & os, shared_ptr const & p) williamr@2: { williamr@2: os << p.get(); williamr@2: return os; williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: // in STLport's no-iostreams mode no iostream symbols can be used williamr@2: #ifndef _STLP_NO_IOSTREAMS williamr@2: williamr@2: # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT) williamr@2: // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL williamr@2: using std::basic_ostream; williamr@2: template basic_ostream & operator<< (basic_ostream & os, shared_ptr const & p) williamr@2: # else williamr@2: template std::basic_ostream & operator<< (std::basic_ostream & os, shared_ptr const & p) williamr@2: # endif williamr@2: { williamr@2: os << p.get(); williamr@2: return os; williamr@2: } williamr@2: williamr@2: #endif // _STLP_NO_IOSTREAMS williamr@2: williamr@2: #endif // __GNUC__ < 3 williamr@2: williamr@2: // get_deleter (experimental) williamr@2: williamr@2: #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ williamr@2: ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ williamr@2: ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) williamr@2: williamr@2: // g++ 2.9x doesn't allow static_cast(void *) williamr@2: // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it williamr@2: williamr@2: template D * get_deleter(shared_ptr const & p) williamr@2: { williamr@2: void const * q = p._internal_get_deleter(typeid(D)); williamr@2: return const_cast(static_cast(q)); williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: template D * get_deleter(shared_ptr const & p) williamr@2: { williamr@2: return static_cast(p._internal_get_deleter(typeid(D))); williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: } // namespace boost williamr@2: williamr@2: #ifdef BOOST_MSVC williamr@2: # pragma warning(pop) williamr@2: #endif williamr@2: williamr@2: #endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) williamr@2: williamr@2: #endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED