forked from boostorg/smart_ptr
Added support for calling enable_shared_from_this::shared_from_this in
constructors. Closes #1696. [SVN r43738]
This commit is contained in:
@ -23,9 +23,32 @@ namespace boost
|
|||||||
|
|
||||||
template<class T> class enable_shared_from_this
|
template<class T> class enable_shared_from_this
|
||||||
{
|
{
|
||||||
|
// dynamic cast to template type doesn't work in constructor, so we have
|
||||||
|
// to use lazy initialization
|
||||||
|
void init_internal_shared_once() const
|
||||||
|
{
|
||||||
|
if(owned() == false && _internal_shared_this == 0)
|
||||||
|
{
|
||||||
|
_internal_shared_this = shared_ptr<T>(dynamic_cast<T *>(const_cast<enable_shared_from_this*>(this)),
|
||||||
|
detail::sp_deleter_wrapper(), detail::ignore_enable_shared_from_this_tag());
|
||||||
|
BOOST_ASSERT(_internal_shared_this.get() == this);
|
||||||
|
_internal_weak_this = _internal_shared_this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool owned() const
|
||||||
|
{
|
||||||
|
return _owned;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef T _internal_element_type; // for bcc 5.5.1
|
||||||
|
mutable shared_ptr<_internal_element_type> _internal_shared_this;
|
||||||
|
mutable weak_ptr<_internal_element_type> _internal_weak_this;
|
||||||
|
mutable bool _owned;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
enable_shared_from_this()
|
enable_shared_from_this():
|
||||||
|
_owned(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,14 +61,20 @@ protected:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~enable_shared_from_this()
|
// virtual destructor because we need a vtable for dynamic_cast from base to derived to work
|
||||||
|
virtual ~enable_shared_from_this()
|
||||||
{
|
{
|
||||||
|
// make sure no dangling shared_ptr objects were created by the
|
||||||
|
// user calling shared_from_this() but never passing ownership of the object
|
||||||
|
// to a shared_ptr.
|
||||||
|
BOOST_ASSERT(owned() || _internal_shared_this.use_count() <= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
shared_ptr<T> shared_from_this()
|
shared_ptr<T> shared_from_this()
|
||||||
{
|
{
|
||||||
|
init_internal_shared_once();
|
||||||
shared_ptr<T> p(_internal_weak_this);
|
shared_ptr<T> p(_internal_weak_this);
|
||||||
BOOST_ASSERT(p.get() == this);
|
BOOST_ASSERT(p.get() == this);
|
||||||
return p;
|
return p;
|
||||||
@ -53,19 +82,21 @@ public:
|
|||||||
|
|
||||||
shared_ptr<T const> shared_from_this() const
|
shared_ptr<T const> shared_from_this() const
|
||||||
{
|
{
|
||||||
|
init_internal_shared_once();
|
||||||
shared_ptr<T const> p(_internal_weak_this);
|
shared_ptr<T const> p(_internal_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
|
template<typename U>
|
||||||
//
|
void _internal_accept_owner(shared_ptr<U> &owner) const
|
||||||
// Please read the documentation, not the code
|
{
|
||||||
//
|
init_internal_shared_once();
|
||||||
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
|
get_deleter<detail::sp_deleter_wrapper>(_internal_shared_this)->set_deleter(owner);
|
||||||
|
owner = _internal_shared_this;
|
||||||
typedef T _internal_element_type; // for bcc 5.5.1
|
_internal_shared_this.reset();
|
||||||
mutable weak_ptr<_internal_element_type> _internal_weak_this;
|
_owned = true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@ -48,6 +48,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;
|
||||||
|
|
||||||
@ -90,9 +91,14 @@ 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 )
|
struct ignore_enable_shared_from_this_tag {};
|
||||||
|
|
||||||
|
template<class T, class Y> void sp_enable_shared_from_this( boost::shared_ptr<Y> * ptr, 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(*ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _MANAGED
|
#ifdef _MANAGED
|
||||||
@ -104,7 +110,7 @@ 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 )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +121,7 @@ inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_poin
|
|||||||
# pragma set woff 3506
|
# pragma set woff 3506
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
|
inline void sp_enable_shared_from_this( ... )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +142,7 @@ 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 >
|
template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
|
||||||
{
|
{
|
||||||
typedef R type;
|
typedef R type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -172,7 +178,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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -183,14 +189,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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// generated copy constructor, assignment, destructor are fine...
|
// generated copy constructor, assignment, destructor are fine...
|
||||||
@ -253,6 +259,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constructor that doesn't trigger enable_shared_from_this code, needed
|
||||||
|
// for enable_shared_from_this internal implementation
|
||||||
|
template<class Y, class D> shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag tag):
|
||||||
|
px(p), pn(p, d)
|
||||||
|
{}
|
||||||
|
|
||||||
#ifndef BOOST_NO_AUTO_PTR
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
template<class Y>
|
template<class Y>
|
||||||
@ -260,7 +272,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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||||
@ -270,7 +282,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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -382,7 +394,7 @@ public:
|
|||||||
BOOST_ASSERT(px != 0);
|
BOOST_ASSERT(px != 0);
|
||||||
return px;
|
return px;
|
||||||
}
|
}
|
||||||
|
|
||||||
T * get() const // never throws
|
T * get() const // never throws
|
||||||
{
|
{
|
||||||
return px;
|
return px;
|
||||||
@ -416,13 +428,13 @@ public:
|
|||||||
( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
|
( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
|
||||||
|
|
||||||
typedef T * (this_type::*unspecified_bool_type)() const;
|
typedef T * (this_type::*unspecified_bool_type)() const;
|
||||||
|
|
||||||
operator unspecified_bool_type() const // never throws
|
operator unspecified_bool_type() const // never throws
|
||||||
{
|
{
|
||||||
return px == 0? 0: &this_type::get;
|
return px == 0? 0: &this_type::get;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
typedef T * this_type::*unspecified_bool_type;
|
typedef T * this_type::*unspecified_bool_type;
|
||||||
|
|
||||||
@ -583,7 +595,7 @@ using std::basic_ostream;
|
|||||||
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
|
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
|
||||||
# else
|
# else
|
||||||
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
|
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
|
||||||
# endif
|
# endif
|
||||||
{
|
{
|
||||||
os << p.get();
|
os << p.get();
|
||||||
return os;
|
return os;
|
||||||
@ -597,6 +609,8 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
|
|||||||
|
|
||||||
// get_deleter
|
// get_deleter
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
|
#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
|
||||||
( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
|
( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
|
||||||
( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
|
( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
|
||||||
@ -604,7 +618,7 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
|
|||||||
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
|
// 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
|
// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
|
||||||
|
|
||||||
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
|
||||||
{
|
{
|
||||||
void const * q = p._internal_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));
|
return const_cast<D *>(static_cast<D const *>(q));
|
||||||
@ -612,18 +626,53 @@ template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
|
template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
|
||||||
{
|
{
|
||||||
return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
|
return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class sp_deleter_wrapper
|
||||||
|
{
|
||||||
|
shared_ptr<const void> _deleter;
|
||||||
|
public:
|
||||||
|
sp_deleter_wrapper()
|
||||||
|
{}
|
||||||
|
void set_deleter(const shared_ptr<const void> &deleter)
|
||||||
|
{
|
||||||
|
_deleter = deleter;
|
||||||
|
}
|
||||||
|
void operator()(const void *)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(_deleter.use_count() <= 1);
|
||||||
|
_deleter.reset();
|
||||||
|
}
|
||||||
|
template<typename D>
|
||||||
|
D* get_deleter() const
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if(del == 0)
|
||||||
|
{
|
||||||
|
detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter<detail::sp_deleter_wrapper>(p);
|
||||||
|
if(del_wrapper) del = del_wrapper->get_deleter<D>();
|
||||||
|
}
|
||||||
|
return del;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
#ifdef BOOST_MSVC
|
#ifdef BOOST_MSVC
|
||||||
# pragma warning(pop)
|
# pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||||
|
|
||||||
|
@ -36,5 +36,6 @@ import testing ;
|
|||||||
[ compile-fail scoped_ptr_eq_fail.cpp ]
|
[ compile-fail scoped_ptr_eq_fail.cpp ]
|
||||||
[ compile-fail scoped_array_eq_fail.cpp ]
|
[ compile-fail scoped_array_eq_fail.cpp ]
|
||||||
[ run esft_regtest.cpp ]
|
[ run esft_regtest.cpp ]
|
||||||
|
[ run esft_constructor_test.cpp ]
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
144
test/esft_constructor_test.cpp
Normal file
144
test/esft_constructor_test.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// 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 && !(a < b) && !(b < a);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
return boost::report_errors();
|
||||||
|
}
|
Reference in New Issue
Block a user