forked from boostorg/smart_ptr
Sync enable_shared_from_this.hpp and shared_ptr.hpp with release.
[SVN r51485]
This commit is contained in:
@@ -13,23 +13,15 @@
|
||||
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
|
||||
template< class T > class enable_shared_from_this;
|
||||
template< class T, class Y > void sp_accept_owner( shared_ptr<Y> * ptr, enable_shared_from_this<T> const * pe );
|
||||
template< class T, class Y > void sp_accept_owner( shared_ptr<Y> * ptr, enable_shared_from_this<T> const * pe, void * /*pd*/ );
|
||||
|
||||
#endif
|
||||
|
||||
template< class T > class enable_shared_from_this
|
||||
template<class T> class enable_shared_from_this
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -46,89 +38,36 @@ protected:
|
||||
return *this;
|
||||
}
|
||||
|
||||
// virtual destructor because we need a vtable for dynamic_cast from base to derived to work
|
||||
virtual ~enable_shared_from_this()
|
||||
~enable_shared_from_this()
|
||||
{
|
||||
BOOST_ASSERT( _shared_count.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
shared_ptr<T> shared_from_this()
|
||||
{
|
||||
init_weak_once();
|
||||
T * p = dynamic_cast<T *>( this );
|
||||
return shared_ptr<T>( detail::shared_count( _weak_count ), p );
|
||||
shared_ptr<T> p(_internal_weak_this);
|
||||
BOOST_ASSERT(p.get() == this);
|
||||
return p;
|
||||
}
|
||||
|
||||
shared_ptr<T const> shared_from_this() const
|
||||
{
|
||||
init_weak_once();
|
||||
T const * p = dynamic_cast<T const *>( this );
|
||||
return shared_ptr<T const>( detail::shared_count( _weak_count ), p );
|
||||
shared_ptr<T const> p(_internal_weak_this);
|
||||
BOOST_ASSERT(p.get() == this);
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
// Note: No, you don't need to initialize _internal_weak_this
|
||||
//
|
||||
// Please read the documentation, not the code
|
||||
//
|
||||
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
|
||||
|
||||
mutable detail::weak_count _weak_count;
|
||||
mutable detail::shared_count _shared_count;
|
||||
|
||||
void init_weak_once() const
|
||||
{
|
||||
if( _weak_count.empty() )
|
||||
{
|
||||
detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap( _shared_count );
|
||||
_weak_count = _shared_count;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
|
||||
template< class U, class Y > friend void sp_accept_owner( shared_ptr<Y> * ptr, enable_shared_from_this<U> const * pe );
|
||||
template< class U, class Y > friend void sp_accept_owner( shared_ptr<Y> * ptr, enable_shared_from_this<U> const * pe, void * /*pd*/ );
|
||||
|
||||
#else
|
||||
|
||||
public:
|
||||
|
||||
#endif
|
||||
|
||||
template<typename U>
|
||||
void sp_accept_owner( shared_ptr<U> & owner ) const
|
||||
{
|
||||
if( _weak_count.use_count() == 0 )
|
||||
{
|
||||
_weak_count = owner.get_shared_count();
|
||||
}
|
||||
else if( !_shared_count.empty() )
|
||||
{
|
||||
BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that
|
||||
detail::sp_deleter_wrapper * pd = detail::basic_get_deleter<detail::sp_deleter_wrapper>( _shared_count );
|
||||
BOOST_ASSERT( pd != 0 );
|
||||
pd->set_deleter( owner.get_shared_count() );
|
||||
|
||||
owner.reset( _shared_count, owner.get() );
|
||||
detail::shared_count().swap( _shared_count );
|
||||
}
|
||||
}
|
||||
typedef T _internal_element_type; // for bcc 5.5.1
|
||||
mutable weak_ptr<_internal_element_type> _internal_weak_this;
|
||||
};
|
||||
|
||||
template< class T, class Y > inline void sp_accept_owner( shared_ptr<Y> * ptr, enable_shared_from_this<T> const * pe )
|
||||
{
|
||||
if( pe != 0 )
|
||||
{
|
||||
pe->sp_accept_owner( *ptr );
|
||||
}
|
||||
}
|
||||
|
||||
template< class T, class Y > inline void sp_accept_owner( shared_ptr<Y> * ptr, enable_shared_from_this<T> const * pe, void * /*pd*/ )
|
||||
{
|
||||
if( pe != 0 )
|
||||
{
|
||||
pe->sp_accept_owner( *ptr );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||
|
@@ -58,8 +58,8 @@
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class shared_ptr;
|
||||
template<class T> class weak_ptr;
|
||||
template<class T> class enable_shared_from_this;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -98,6 +98,43 @@ template<> struct shared_ptr_traits<void const volatile>
|
||||
|
||||
#endif
|
||||
|
||||
// enable_shared_from_this support
|
||||
|
||||
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 )
|
||||
{
|
||||
if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
|
||||
}
|
||||
|
||||
#ifdef _MANAGED
|
||||
|
||||
// Avoid C4793, ... causes native code generation
|
||||
|
||||
struct sp_any_pointer
|
||||
{
|
||||
template<class T> sp_any_pointer( T* ) {}
|
||||
};
|
||||
|
||||
inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer )
|
||||
{
|
||||
}
|
||||
|
||||
#else // _MANAGED
|
||||
|
||||
#ifdef sgi
|
||||
// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed
|
||||
# pragma set woff 3506
|
||||
#endif
|
||||
|
||||
inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef sgi
|
||||
# pragma reset woff 3506
|
||||
#endif
|
||||
|
||||
#endif // _MANAGED
|
||||
|
||||
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
|
||||
|
||||
// rvalue auto_ptr support based on a technique by Dave Abrahams
|
||||
@@ -109,38 +146,12 @@ template< class T, class R > struct sp_enable_if_auto_ptr
|
||||
template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
|
||||
{
|
||||
typedef R type;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// sp_accept_owner
|
||||
|
||||
#ifdef _MANAGED
|
||||
|
||||
// Avoid C4793, ... causes native code generation
|
||||
|
||||
struct sp_any_pointer
|
||||
{
|
||||
template<class T> sp_any_pointer( T* ) {}
|
||||
};
|
||||
|
||||
inline void sp_accept_owner( sp_any_pointer, sp_any_pointer )
|
||||
{
|
||||
}
|
||||
|
||||
inline void sp_accept_owner( sp_any_pointer, sp_any_pointer, sp_any_pointer )
|
||||
{
|
||||
}
|
||||
|
||||
#else // _MANAGED
|
||||
|
||||
inline void sp_accept_owner( ... )
|
||||
{
|
||||
}
|
||||
|
||||
#endif // _MANAGED
|
||||
|
||||
//
|
||||
// shared_ptr
|
||||
@@ -171,7 +182,7 @@ public:
|
||||
template<class Y>
|
||||
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
|
||||
{
|
||||
sp_accept_owner( this, p );
|
||||
boost::detail::sp_enable_shared_from_this( pn, p, p );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -180,18 +191,16 @@ public:
|
||||
// shared_ptr will release p by calling d(p)
|
||||
//
|
||||
|
||||
template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
|
||||
template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
|
||||
{
|
||||
D * pd = static_cast<D *>( pn.get_deleter( BOOST_SP_TYPEID(D) ) );
|
||||
sp_accept_owner( this, p, pd );
|
||||
boost::detail::sp_enable_shared_from_this( pn, p, p );
|
||||
}
|
||||
|
||||
// As above, but with allocator. A's copy constructor shall not throw.
|
||||
|
||||
template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
|
||||
{
|
||||
D * pd = static_cast<D *>( pn.get_deleter( BOOST_SP_TYPEID(D) ) );
|
||||
sp_accept_owner( this, p, pd );
|
||||
boost::detail::sp_enable_shared_from_this( pn, p, p );
|
||||
}
|
||||
|
||||
// generated copy constructor, assignment, destructor are fine...
|
||||
@@ -238,10 +247,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
shared_ptr( detail::shared_count const & c, T * p ): px( p ), pn( c ) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
// aliasing
|
||||
template< class Y >
|
||||
shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
|
||||
@@ -283,8 +288,7 @@ public:
|
||||
{
|
||||
Y * tmp = r.get();
|
||||
pn = boost::detail::shared_count(r);
|
||||
|
||||
sp_accept_owner( this, tmp );
|
||||
boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||
@@ -294,8 +298,7 @@ public:
|
||||
{
|
||||
typename Ap::element_type * tmp = r.get();
|
||||
pn = boost::detail::shared_count( r );
|
||||
|
||||
sp_accept_owner( this, tmp );
|
||||
boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
|
||||
}
|
||||
|
||||
|
||||
@@ -364,10 +367,6 @@ public:
|
||||
r.px = 0;
|
||||
}
|
||||
|
||||
shared_ptr(detail::shared_count && c, T * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
shared_ptr & operator=( shared_ptr && r ) // never throws
|
||||
{
|
||||
this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
|
||||
@@ -409,18 +408,6 @@ public:
|
||||
this_type( r, p ).swap( *this );
|
||||
}
|
||||
|
||||
void reset( detail::shared_count const & c, T * p )
|
||||
{
|
||||
this_type( c, p ).swap( *this );
|
||||
}
|
||||
|
||||
#if defined( BOOST_HAS_RVALUE_REFS )
|
||||
void reset( detail::shared_count && c, T * p )
|
||||
{
|
||||
this_type( static_cast< detail::shared_count && >( c ), p ).swap( *this );
|
||||
}
|
||||
#endif
|
||||
|
||||
reference operator* () const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
@@ -506,16 +493,16 @@ public:
|
||||
pn.swap(other.pn);
|
||||
}
|
||||
|
||||
detail::shared_count const & get_shared_count() const // never throws
|
||||
{
|
||||
return pn;
|
||||
}
|
||||
|
||||
template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
|
||||
{
|
||||
return pn < rhs.pn;
|
||||
}
|
||||
|
||||
void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const
|
||||
{
|
||||
return pn.get_deleter( ti );
|
||||
}
|
||||
|
||||
bool _internal_equiv( shared_ptr const & r ) const
|
||||
{
|
||||
return px == r.px && pn == r.pn;
|
||||
@@ -652,8 +639,6 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
|
||||
|
||||
// get_deleter
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
|
||||
( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
|
||||
( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
|
||||
@@ -661,75 +646,21 @@ namespace detail
|
||||
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
|
||||
// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
|
||||
|
||||
template<class D> D * basic_get_deleter(shared_count const & c)
|
||||
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
||||
{
|
||||
void const * q = c.get_deleter(BOOST_SP_TYPEID(D));
|
||||
void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
|
||||
return const_cast<D *>(static_cast<D const *>(q));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<class D> D * basic_get_deleter(shared_count const & c)
|
||||
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
||||
{
|
||||
return static_cast<D *>(c.get_deleter(BOOST_SP_TYPEID(D)));
|
||||
return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
class sp_deleter_wrapper
|
||||
{
|
||||
detail::shared_count _deleter;
|
||||
public:
|
||||
sp_deleter_wrapper()
|
||||
{}
|
||||
void set_deleter(shared_count const &deleter)
|
||||
{
|
||||
_deleter = deleter;
|
||||
}
|
||||
void operator()(const void *)
|
||||
{
|
||||
BOOST_ASSERT(_deleter.use_count() <= 1);
|
||||
detail::shared_count().swap( _deleter );
|
||||
}
|
||||
template<typename D>
|
||||
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 )
|
||||
D* get_deleter( D* ) const
|
||||
#else
|
||||
D* get_deleter() const
|
||||
#endif
|
||||
{
|
||||
return boost::detail::basic_get_deleter<D>(_deleter);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class D, class T> D * get_deleter( shared_ptr<T> const & p )
|
||||
{
|
||||
D *del = detail::basic_get_deleter<D>( p.get_shared_count() );
|
||||
|
||||
if( del == 0 )
|
||||
{
|
||||
detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter<detail::sp_deleter_wrapper>(p.get_shared_count());
|
||||
|
||||
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 )
|
||||
|
||||
if( del_wrapper ) del = del_wrapper->get_deleter( (D*)0 );
|
||||
|
||||
#elif defined( __GNUC__ ) && BOOST_WORKAROUND( __GNUC__, < 4 )
|
||||
|
||||
if( del_wrapper ) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter<D>();
|
||||
|
||||
#else
|
||||
|
||||
if( del_wrapper ) del = del_wrapper->get_deleter<D>();
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return del;
|
||||
}
|
||||
|
||||
// atomic access
|
||||
|
||||
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
|
||||
|
Reference in New Issue
Block a user