Fix enable_shared_from_this-related tickets in trunk. Refs #2126. Refs #2584.

[SVN r51581]
This commit is contained in:
Peter Dimov
2009-03-03 19:25:26 +00:00
parent 68c939ec5a
commit 9c55fbc6c2
14 changed files with 824 additions and 407 deletions

View File

@ -4,11 +4,11 @@
//
// enable_shared_from_this.hpp
//
// Copyright (c) 2002 Peter Dimov
// Copyright 2002, 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
//
@ -46,26 +46,32 @@ public:
shared_ptr<T> shared_from_this()
{
shared_ptr<T> p(_internal_weak_this);
BOOST_ASSERT(p.get() == this);
shared_ptr<T> p( weak_this_ );
BOOST_ASSERT( p.get() == this );
return p;
}
shared_ptr<T const> shared_from_this() const
{
shared_ptr<T const> p(_internal_weak_this);
BOOST_ASSERT(p.get() == this);
shared_ptr<T const> p( weak_this_ );
BOOST_ASSERT( p.get() == this );
return p;
}
// 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
public: // actually private, but avoids compiler template friendship issues
typedef T _internal_element_type; // for bcc 5.5.1
mutable weak_ptr<_internal_element_type> _internal_weak_this;
// Note: invoked automatically by shared_ptr; do not call
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
{
if( weak_this_.expired() )
{
weak_this_ = shared_ptr<T>( *ppx, py );
}
}
private:
mutable weak_ptr<T> weak_this_;
};
} // namespace boost

View File

@ -105,10 +105,13 @@ template< class T > boost::shared_ptr< T > make_shared()
void * pv = pd->address();
new( pv ) T();
::new( pv ) T();
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a )
@ -119,10 +122,13 @@ template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a
void * pv = pd->address();
new( pv ) T();
::new( pv ) T();
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
@ -137,10 +143,13 @@ template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && .
void * pv = pd->address();
new( pv ) T( detail::forward<Args>( args )... );
::new( pv ) T( detail::forward<Args>( args )... );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args )
@ -151,10 +160,13 @@ template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shar
void * pv = pd->address();
new( pv ) T( detail::forward<Args>( args )... );
::new( pv ) T( detail::forward<Args>( args )... );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
#else
@ -170,10 +182,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1 )
void * pv = pd->address();
new( pv ) T( a1 );
::new( pv ) T( a1 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1 >
@ -185,10 +200,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 )
void * pv = pd->address();
new( pv ) T( a1 );
::new( pv ) T( a1 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2 >
@ -200,10 +218,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 )
void * pv = pd->address();
new( pv ) T( a1, a2 );
::new( pv ) T( a1, a2 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2 >
@ -215,10 +236,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2 );
::new( pv ) T( a1, a2 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3 >
@ -230,10 +254,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3
void * pv = pd->address();
new( pv ) T( a1, a2, a3 );
::new( pv ) T( a1, a2, a3 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3 >
@ -245,10 +272,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2, a3 );
::new( pv ) T( a1, a2, a3 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4 >
@ -260,10 +290,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4 );
::new( pv ) T( a1, a2, a3, a4 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4 >
@ -275,10 +308,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4 );
::new( pv ) T( a1, a2, a3, a4 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5 >
@ -290,10 +326,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5 );
::new( pv ) T( a1, a2, a3, a4, a5 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
@ -305,10 +344,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5 );
::new( pv ) T( a1, a2, a3, a4, a5 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
@ -320,10 +362,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6 );
::new( pv ) T( a1, a2, a3, a4, a5, a6 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
@ -335,10 +380,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6 );
::new( pv ) T( a1, a2, a3, a4, a5, a6 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
@ -350,10 +398,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
@ -365,10 +416,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
@ -380,10 +434,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
@ -395,10 +452,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
@ -410,10 +470,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3,
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
@ -425,10 +488,13 @@ boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a
void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
pd->set_initialized();
return boost::shared_ptr< T >( pt, static_cast< T* >( pv ) );
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
#endif

View File

@ -58,6 +58,7 @@
namespace boost
{
template<class T> class shared_ptr;
template<class T> class weak_ptr;
template<class T> class enable_shared_from_this;
@ -100,9 +101,12 @@ template<> struct shared_ptr_traits<void const volatile>
// 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 )
template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
{
if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
if( pe != 0 )
{
pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
}
}
#ifdef _MANAGED
@ -114,25 +118,16 @@ 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 )
inline void sp_enable_shared_from_this( sp_any_pointer, 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*/, ... )
inline void sp_enable_shared_from_this( ... )
{
}
#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 )
@ -182,7 +177,7 @@ public:
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
{
boost::detail::sp_enable_shared_from_this( pn, p, p );
boost::detail::sp_enable_shared_from_this( this, p, p );
}
//
@ -193,14 +188,14 @@ public:
template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
{
boost::detail::sp_enable_shared_from_this( pn, p, p );
boost::detail::sp_enable_shared_from_this( this, 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 )
{
boost::detail::sp_enable_shared_from_this( pn, p, p );
boost::detail::sp_enable_shared_from_this( this, p, p );
}
// generated copy constructor, assignment, destructor are fine...
@ -288,7 +283,7 @@ public:
{
Y * tmp = r.get();
pn = boost::detail::shared_count(r);
boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
}
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
@ -298,7 +293,7 @@ public:
{
typename Ap::element_type * tmp = r.get();
pn = boost::detail::shared_count( r );
boost::detail::sp_enable_shared_from_this( pn, tmp, tmp );
boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
}

View File

@ -48,5 +48,9 @@ import testing ;
[ run ip_convertible_test.cpp ]
[ run allocate_shared_test.cpp ]
[ run sp_atomic_test.cpp ]
[ run esft_void_test.cpp ]
[ run esft_second_ptr_test.cpp ]
[ run make_shared_esft_test.cpp ]
[ run allocate_shared_esft_test.cpp ]
;
}

View File

@ -0,0 +1,264 @@
// allocate_shared_esft_test.cpp
//
// Copyright 2007-2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <memory>
class X: public boost::enable_shared_from_this<X>
{
private:
X( X const & );
X & operator=( X const & );
public:
static int instances;
explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>() );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
return boost::report_errors();
}

View File

@ -10,6 +10,7 @@
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstddef>
class X
{
@ -18,6 +19,14 @@ private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t );
void operator delete( void * p )
{
// lack of this definition causes link errors on MSVC
::operator delete( p );
}
public:
static int instances;

View File

@ -1,169 +0,0 @@
//
// esft_constructor_test.cpp
//
// A test for the new enable_shared_from_this support for calling
// shared_from_this from constructors (that is, prior to the
// object's ownership being passed to an external shared_ptr).
//
// Copyright (c) 2008 Frank Mori Hess
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <memory>
class X: public boost::enable_shared_from_this< X >
{
private:
int destroyed_;
int deleted_;
int expected_;
private:
X( X const& );
X& operator=( X const& );
public:
static int instances;
public:
explicit X( int expected, boost::shared_ptr<X> *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected )
{
++instances;
if( early_px ) *early_px = shared_from_this();
}
~X()
{
BOOST_TEST( deleted_ == expected_ );
BOOST_TEST( destroyed_ == 0 );
++destroyed_;
--instances;
}
typedef void (*deleter_type)( X* );
static void deleter( X * px )
{
++px->deleted_;
}
static void deleter2( X * px )
{
++px->deleted_;
delete px;
}
};
int X::instances = 0;
template<typename T, typename U>
bool are_shared_owners(const boost::shared_ptr<T> &a, const boost::shared_ptr<U> &b)
{
return !(a < b) && !(b < a);
}
struct Y: public boost::enable_shared_from_this<Y>
{};
int main()
{
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> early_px;
X* x = new X( 1, &early_px );
BOOST_TEST( early_px.use_count() > 0 );
BOOST_TEST( boost::get_deleter<X::deleter_type>(early_px) == 0 );
boost::shared_ptr<X> px( x, &X::deleter2 );
BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
BOOST_TEST(are_shared_owners(early_px, px));
px.reset();
BOOST_TEST( early_px.use_count() == 1 );
BOOST_TEST( X::instances == 1 );
X::deleter_type *pd = boost::get_deleter<X::deleter_type>(early_px);
BOOST_TEST(pd && *pd == &X::deleter2 );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> early_px;
X* x = new X( 1, &early_px );
boost::weak_ptr<X> early_weak_px = early_px;
early_px.reset();
BOOST_TEST( !early_weak_px.expired() );
boost::shared_ptr<X> px( x, &X::deleter2 );
BOOST_TEST( px.use_count() == 1 );
BOOST_TEST( X::instances == 1 );
BOOST_TEST(are_shared_owners(early_weak_px.lock(), px));
px.reset();
BOOST_TEST( early_weak_px.expired() );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<X> early_px;
X x( 1, &early_px );
BOOST_TEST( early_px.use_count() > 0 );
boost::shared_ptr<X> px( &x, &X::deleter );
BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 );
early_px.reset();
BOOST_TEST( px.use_count() == 1 );
BOOST_TEST( X::instances == 1 );
px.reset();
try
{
x.shared_from_this();
BOOST_ERROR("x did not throw bad_weak_ptr");
}
catch( const boost::bad_weak_ptr &err)
{}
}
BOOST_TEST( X::instances == 0 );
{
boost::weak_ptr<X> early_weak_px;
{
boost::shared_ptr<X> early_px;
X x( 0, &early_px );
early_weak_px = early_px;
early_px.reset();
BOOST_TEST( !early_weak_px.expired() );
BOOST_TEST( X::instances == 1 );
}
BOOST_TEST( early_weak_px.expired() );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr<Y> px(new Y());
Y y(*px);
px.reset();
try
{
y.shared_from_this();
}
catch( const boost::bad_weak_ptr &err)
{
BOOST_ERROR("y threw bad_weak_ptr");
}
}
return boost::report_errors();
}

View File

@ -0,0 +1,51 @@
//
// esft_second_ptr_test.cpp
//
// This test has been extracted from a real
// scenario that occurs in Boost.Python
//
// Copyright 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
//
class X: public boost::enable_shared_from_this<X>
{
};
void null_deleter( void const* )
{
}
int main()
{
boost::shared_ptr<X> px( new X );
{
boost::shared_ptr<X> px2( px.get(), null_deleter );
BOOST_TEST( px == px2 );
}
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
return boost::report_errors();
}

41
test/esft_void_test.cpp Normal file
View File

@ -0,0 +1,41 @@
//
// esft_void_test.cpp
//
// Copyright 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
//
class X: public boost::enable_shared_from_this<X>
{
};
int main()
{
boost::shared_ptr< void const volatile > pv( new X );
boost::shared_ptr< void > pv2 = boost::const_pointer_cast< void >( pv );
boost::shared_ptr< X > px = boost::static_pointer_cast< X >( pv2 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
return boost::report_errors();
}

View File

@ -0,0 +1,263 @@
// make_shared_esft_test.cpp
//
// Copyright 2007-2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
class X: public boost::enable_shared_from_this<X>
{
private:
X( X const & );
X & operator=( X const & );
public:
static int instances;
explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >();
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::make_shared< X >( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
return boost::report_errors();
}

View File

@ -10,6 +10,7 @@
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstddef>
class X
{
@ -18,6 +19,14 @@ private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t );
void operator delete( void * p )
{
// lack of this definition causes link errors on MSVC
::operator delete( p );
}
public:
static int instances;

View File

@ -55,16 +55,23 @@ void test()
BOOST_TEST(py.get() != 0);
BOOST_TEST(py.use_count() == 1);
boost::shared_ptr<X> px = py->getX();
BOOST_TEST(px.get() != 0);
BOOST_TEST(py.use_count() == 2);
try
{
boost::shared_ptr<X> px = py->getX();
BOOST_TEST(px.get() != 0);
BOOST_TEST(py.use_count() == 2);
px->f();
px->f();
boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == py2.get());
BOOST_TEST(!(py < py2 || py2 < py));
BOOST_TEST(py.use_count() == 3);
boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == py2.get());
BOOST_TEST(!(py < py2 || py2 < py));
BOOST_TEST(py.use_count() == 3);
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "py->getX() failed" );
}
}
void test2();
@ -124,19 +131,25 @@ void test3()
{
boost::shared_ptr<V> p(new V);
boost::shared_ptr<V> q = p->shared_from_this();
BOOST_TEST(p == q);
BOOST_TEST(!(p < q) && !(q < p));
try
{
boost::shared_ptr<V> q = p->shared_from_this();
BOOST_TEST(p == q);
BOOST_TEST(!(p < q) && !(q < p));
}
catch( boost::bad_weak_ptr const & )
{
BOOST_ERROR( "p->shared_from_this() failed" );
}
V v2(*p);
try
{
boost::shared_ptr<V> r = v2.shared_from_this();
BOOST_TEST( p < r || r < p );
BOOST_TEST( r.get() == &v2 );
BOOST_ERROR("v2.shared_from_this() failed to throw");
}
catch(boost::bad_weak_ptr const &)
catch( boost::bad_weak_ptr const & )
{
}
@ -147,7 +160,7 @@ void test3()
BOOST_TEST(p == r);
BOOST_TEST(!(p < r) && !(r < p));
}
catch(boost::bad_weak_ptr const &)
catch( boost::bad_weak_ptr const & )
{
BOOST_ERROR("p->shared_from_this() threw bad_weak_ptr after *p = V()");
}

View File

@ -8,6 +8,8 @@
// http://www.boost.org/LICENSE_1_0.txt
//
#if defined( BOOST_HAS_RVALUE_REFS )
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
@ -93,3 +95,12 @@ int main()
return boost::report_errors();
}
#else // !defined( BOOST_HAS_RVALUE_REFS )
int main()
{
return 0;
}
#endif

View File

@ -1,146 +0,0 @@
//
// sp_accept_owner_test.cpp
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
namespace N
{
struct D;
struct X
{
X * px_;
D * pd_;
void * pv_;
X(): px_( 0 ), pd_( 0 ), pv_( 0 )
{
}
};
struct D
{
template<class T> void operator()( T * p ) const { delete p; }
};
} // namespace N
#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP )
namespace N
{
#else
namespace boost
{
#endif
template<class Y> inline void sp_accept_owner( boost::shared_ptr<Y> * ps, ::N::X * px )
{
std::cout << "sp_accept_owner( " << ps << ", " << px << " )\n";
BOOST_TEST( ps->get() == px );
if( px != 0 )
{
px->px_ = px;
}
}
template<class Y> inline void sp_accept_owner( boost::shared_ptr<Y> * ps, ::N::X * px, ::N::D * pd )
{
std::cout << "sp_accept_owner( " << ps << ", " << px << ", (D*)" << pd << " )\n";
BOOST_TEST( ps->get() == px );
if( px != 0 )
{
px->px_ = px;
px->pd_ = pd;
}
}
template<class Y> inline void sp_accept_owner( boost::shared_ptr<Y> * ps, ::N::X * px, void * pv )
{
std::cout << "sp_accept_owner( " << ps << ", " << px << ", (void*)" << pv << " )\n";
BOOST_TEST( ps->get() == px );
if( px != 0 )
{
px->px_ = px;
px->pv_ = pv;
}
}
} // namespace N or boost
struct D2
{
template<class T> void operator()( T * p ) const { delete p; }
};
template<class T> void test( T* = 0 )
{
{
boost::shared_ptr<T> p( static_cast< T* >( 0 ) );
}
{
T * p = new T;
boost::shared_ptr<T> q( p );
BOOST_TEST( q->px_ == p );
BOOST_TEST( q->pd_ == 0 );
BOOST_TEST( q->pv_ == 0 );
}
{
T * p = new T;
boost::shared_ptr<T> q( p, N::D() );
BOOST_TEST( q->px_ == p );
BOOST_TEST( q->pd_ != 0 );
BOOST_TEST( q->pv_ == 0 );
}
{
T * p = new T;
boost::shared_ptr<T> q( p, D2() );
BOOST_TEST( q->px_ == p );
BOOST_TEST( q->pd_ == 0 );
BOOST_TEST( q->pv_ != 0 );
}
}
namespace N2
{
struct Y: public virtual N::X
{
};
} // namespace N2
int main()
{
test<N::X>();
test<N2::Y>();
return boost::report_errors();
}