Merge [51581] to release. Fixes #2126. Fixes #2584.

[SVN r51632]
This commit is contained in:
Peter Dimov
2009-03-05 23:06:17 +00:00
parent 5a2771e585
commit 22f1b092c9
12 changed files with 824 additions and 92 deletions

View File

@@ -4,11 +4,11 @@
// //
// enable_shared_from_this.hpp // 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 // Distributed under the Boost Software License, Version 1.0.
// accompanying file LICENSE_1_0.txt or copy at // See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt
// //
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // 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> shared_from_this()
{ {
shared_ptr<T> p(_internal_weak_this); shared_ptr<T> p( weak_this_ );
BOOST_ASSERT(p.get() == this); BOOST_ASSERT( p.get() == this );
return p; return p;
} }
shared_ptr<T const> shared_from_this() const shared_ptr<T const> shared_from_this() const
{ {
shared_ptr<T const> p(_internal_weak_this); shared_ptr<T const> p( weak_this_ );
BOOST_ASSERT(p.get() == this); BOOST_ASSERT( p.get() == this );
return p; return p;
} }
// Note: No, you don't need to initialize _internal_weak_this public: // actually private, but avoids compiler template friendship issues
//
// Please read the documentation, not the code
//
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
typedef T _internal_element_type; // for bcc 5.5.1 // Note: invoked automatically by shared_ptr; do not call
mutable weak_ptr<_internal_element_type> _internal_weak_this; 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 } // namespace boost

View File

@@ -105,10 +105,13 @@ template< class T > boost::shared_ptr< T > make_shared()
void * pv = pd->address(); void * pv = pd->address();
new( pv ) T(); ::new( pv ) T();
pd->set_initialized(); 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 ) 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(); void * pv = pd->address();
new( pv ) T(); ::new( pv ) T();
pd->set_initialized(); 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 ) #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(); void * pv = pd->address();
new( pv ) T( detail::forward<Args>( args )... ); ::new( pv ) T( detail::forward<Args>( args )... );
pd->set_initialized(); 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 ) 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(); void * pv = pd->address();
new( pv ) T( detail::forward<Args>( args )... ); ::new( pv ) T( detail::forward<Args>( args )... );
pd->set_initialized(); 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 #else
@@ -170,10 +182,13 @@ boost::shared_ptr< T > make_shared( A1 const & a1 )
void * pv = pd->address(); void * pv = pd->address();
new( pv ) T( a1 ); ::new( pv ) T( a1 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1 ); ::new( pv ) T( a1 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2 ); ::new( pv ) T( a1, a2 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2 ); ::new( pv ) T( a1, a2 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2, a3 ); ::new( pv ) T( a1, a2, a3 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2, a3 ); ::new( pv ) T( a1, a2, a3 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4 ); ::new( pv ) T( a1, a2, a3, a4 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4 ); ::new( pv ) T( a1, a2, a3, a4 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5 ); ::new( pv ) T( a1, a2, a3, a4, a5 );
pd->set_initialized(); 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 > 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(); void * pv = pd->address();
new( pv ) T( a1, a2, a3, a4, a5 ); ::new( pv ) T( a1, a2, a3, a4, a5 );
pd->set_initialized(); 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 > 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(); 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(); 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 > 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(); 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(); 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 > 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(); 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(); 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 > 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(); 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(); 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 > 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(); 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(); 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 > 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(); 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(); 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 > 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(); 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(); 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 > 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(); 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(); 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 #endif

View File

@@ -58,6 +58,7 @@
namespace boost namespace boost
{ {
template<class T> class shared_ptr;
template<class T> class weak_ptr; template<class T> class weak_ptr;
template<class T> class enable_shared_from_this; 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 // 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 #ifdef _MANAGED
@@ -114,25 +118,16 @@ struct sp_any_pointer
template<class T> sp_any_pointer( T* ) {} 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 #else // _MANAGED
#ifdef sgi inline void sp_enable_shared_from_this( ... )
// 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 #endif // _MANAGED
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
@@ -182,7 +177,7 @@ public:
template<class Y> template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete 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) 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. // 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 ) 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... // generated copy constructor, assignment, destructor are fine...
@@ -288,7 +283,7 @@ public:
{ {
Y * tmp = r.get(); Y * tmp = r.get();
pn = boost::detail::shared_count(r); 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 ) #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
@@ -298,7 +293,7 @@ public:
{ {
typename Ap::element_type * tmp = r.get(); typename Ap::element_type * tmp = r.get();
pn = boost::detail::shared_count( r ); 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 ip_convertible_test.cpp ]
[ run allocate_shared_test.cpp ] [ run allocate_shared_test.cpp ]
[ run sp_atomic_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/make_shared.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <cstddef>
class X class X
{ {
@@ -18,6 +19,14 @@ private:
X( X const & ); X( X const & );
X & operator=( 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: public:
static int instances; static int instances;

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/make_shared.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <cstddef>
class X class X
{ {
@@ -18,6 +19,14 @@ private:
X( X const & ); X( X const & );
X & operator=( 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: public:
static int instances; static int instances;

View File

@@ -55,16 +55,23 @@ void test()
BOOST_TEST(py.get() != 0); BOOST_TEST(py.get() != 0);
BOOST_TEST(py.use_count() == 1); BOOST_TEST(py.use_count() == 1);
boost::shared_ptr<X> px = py->getX(); try
BOOST_TEST(px.get() != 0); {
BOOST_TEST(py.use_count() == 2); 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::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == py2.get()); BOOST_TEST(py.get() == py2.get());
BOOST_TEST(!(py < py2 || py2 < py)); BOOST_TEST(!(py < py2 || py2 < py));
BOOST_TEST(py.use_count() == 3); BOOST_TEST(py.use_count() == 3);
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "py->getX() failed" );
}
} }
void test2(); void test2();
@@ -124,19 +131,25 @@ void test3()
{ {
boost::shared_ptr<V> p(new V); boost::shared_ptr<V> p(new V);
boost::shared_ptr<V> q = p->shared_from_this(); try
BOOST_TEST(p == q); {
BOOST_TEST(!(p < q) && !(q < p)); 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); V v2(*p);
try try
{ {
boost::shared_ptr<V> r = v2.shared_from_this(); boost::shared_ptr<V> r = v2.shared_from_this();
BOOST_TEST( p < r || r < p ); BOOST_ERROR("v2.shared_from_this() failed to throw");
BOOST_TEST( r.get() == &v2 );
} }
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);
BOOST_TEST(!(p < r) && !(r < p)); 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()"); 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 // http://www.boost.org/LICENSE_1_0.txt
// //
#if defined( BOOST_HAS_RVALUE_REFS )
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
@@ -93,3 +95,12 @@ int main()
return boost::report_errors(); return boost::report_errors();
} }
#else // !defined( BOOST_HAS_RVALUE_REFS )
int main()
{
return 0;
}
#endif