Sync enable_shared_from_this.hpp and shared_ptr.hpp with release.

[SVN r51485]
This commit is contained in:
Peter Dimov
2009-02-28 20:02:12 +00:00
parent c40b306647
commit 13f91c15f0
2 changed files with 71 additions and 201 deletions

View File

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

View File

@@ -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)