diff --git a/include/boost/smart_ptr/enable_shared_from_raw.hpp b/include/boost/smart_ptr/enable_shared_from_raw.hpp new file mode 100644 index 0000000..b5a03aa --- /dev/null +++ b/include/boost/smart_ptr/enable_shared_from_raw.hpp @@ -0,0 +1,157 @@ +#ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED +#define BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED + +// +// enable_shared_from_raw.hpp +// +// Copyright 2002, 2009 Peter Dimov +// Copyright 2008-2009 Frank Mori Hess +// +// 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 +#include +#include +#include +#include + +namespace boost +{ +template boost::shared_ptr shared_from_raw(T *); + +namespace detail +{ +template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe ); + +class esft2_deleter_wrapper +{ +private: + + shared_ptr deleter_; + +public: + + esft2_deleter_wrapper() + { + } + + template< class T > void set_deleter( shared_ptr const & deleter ) + { + deleter_ = deleter; + } + + template< class T> void operator()( T* ) + { + BOOST_ASSERT( deleter_.use_count() <= 1 ); + deleter_.reset(); + } +}; + +} // namespace detail + +class enable_shared_from_raw +{ +protected: + + enable_shared_from_raw() + { + } + + enable_shared_from_raw( enable_shared_from_raw const & ) + { + } + + enable_shared_from_raw & operator=( enable_shared_from_raw const & ) + { + return *this; + } + + ~enable_shared_from_raw() + { + BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist + } + +private: + + mutable weak_ptr weak_this_; + mutable shared_ptr shared_this_; + +private: + + void init_weak_once() const + { + if( weak_this_.expired() ) + { + shared_this_.reset( static_cast(0), detail::esft2_deleter_wrapper() ); + weak_this_ = shared_this_; + } + } + +#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS +public: +#else +private: + template friend class shared_ptr; + template friend boost::shared_ptr shared_from_raw(T *); + template< class X, class Y > friend inline void detail::sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe ); +#endif + + shared_ptr shared_from_this() + { + init_weak_once(); + return shared_ptr( weak_this_ ); + } + + shared_ptr shared_from_this() const + { + init_weak_once(); + return shared_ptr( weak_this_ ); + } + + // Note: invoked automatically by shared_ptr; do not call + template void _internal_accept_owner( shared_ptr * ppx, Y * py ) const + { + BOOST_ASSERT( ppx != 0 ); + + if( weak_this_.expired() ) + { + weak_this_ = *ppx; + } + else if( shared_this_.use_count() != 0 ) + { + BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that + + detail::esft2_deleter_wrapper * pd = boost::get_deleter( shared_this_ ); + BOOST_ASSERT( pd != 0 ); + + pd->set_deleter( *ppx ); + + ppx->reset( shared_this_, ppx->get() ); + shared_this_.reset(); + } + } +}; + +template +boost::shared_ptr shared_from_raw(T *p) +{ + return boost::shared_ptr(p->enable_shared_from_raw::shared_from_this(), p); +} + +namespace detail +{ + template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe ) + { + if( pe != 0 ) + { + pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); + } + } +} // namepsace detail + +} // namespace boost + +#endif // #ifndef BOOST_ENABLE_SHARED_FROM_RAW_HPP_INCLUDED diff --git a/include/boost/smart_ptr/enable_shared_from_this2.hpp b/include/boost/smart_ptr/enable_shared_from_this2.hpp deleted file mode 100644 index a5bfcff..0000000 --- a/include/boost/smart_ptr/enable_shared_from_this2.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED -#define BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED - -// -// enable_shared_from_this2.hpp -// -// Copyright 2002, 2009 Peter Dimov -// Copyright 2008 Frank Mori Hess -// -// 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 -#include -#include -#include - -namespace boost -{ - -namespace detail -{ - -class esft2_deleter_wrapper -{ -private: - - shared_ptr deleter_; - -public: - - esft2_deleter_wrapper() - { - } - - template< class T > void set_deleter( shared_ptr const & deleter ) - { - deleter_ = deleter; - } - - template< class T> void operator()( T* ) - { - BOOST_ASSERT( deleter_.use_count() <= 1 ); - deleter_.reset(); - } -}; - -} // namespace detail - -template< class T > class enable_shared_from_this2 -{ -protected: - - enable_shared_from_this2() - { - } - - enable_shared_from_this2( enable_shared_from_this2 const & ) - { - } - - enable_shared_from_this2 & operator=( enable_shared_from_this2 const & ) - { - return *this; - } - - ~enable_shared_from_this2() - { - BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist - } - -private: - - mutable weak_ptr weak_this_; - mutable shared_ptr shared_this_; - -public: - - shared_ptr shared_from_this() - { - init_weak_once(); - return shared_ptr( weak_this_ ); - } - - shared_ptr shared_from_this() const - { - init_weak_once(); - return shared_ptr( weak_this_ ); - } - -private: - - void init_weak_once() const - { - if( weak_this_._empty() ) - { - shared_this_.reset( static_cast< T* >( 0 ), detail::esft2_deleter_wrapper() ); - weak_this_ = shared_this_; - } - } - -public: // actually private, but avoids compiler template friendship issues - - // Note: invoked automatically by shared_ptr; do not call - template void _internal_accept_owner( shared_ptr * ppx, Y * py ) const - { - BOOST_ASSERT( ppx != 0 ); - - if( weak_this_.use_count() == 0 ) - { - weak_this_ = shared_ptr( *ppx, py ); - } - else if( shared_this_.use_count() != 0 ) - { - BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that - - detail::esft2_deleter_wrapper * pd = boost::get_deleter( shared_this_ ); - BOOST_ASSERT( pd != 0 ); - - pd->set_deleter( *ppx ); - - ppx->reset( shared_this_, ppx->get() ); - shared_this_.reset(); - } - } -}; - -} // namespace boost - -#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index 1b367f0..e29c376 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -61,7 +61,7 @@ namespace boost template class shared_ptr; template class weak_ptr; template class enable_shared_from_this; -template class enable_shared_from_this2; +class enable_shared_from_raw; namespace detail { @@ -110,13 +110,7 @@ template< class X, class Y, class T > inline void sp_enable_shared_from_this( bo } } -template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe ) -{ - if( pe != 0 ) - { - pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) ); - } -} +template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr * ppx, Y const * py, boost::enable_shared_from_raw const * pe ); #ifdef _MANAGED diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp index ced24e2..ad0fb11 100644 --- a/test/esft_constructor_test.cpp +++ b/test/esft_constructor_test.cpp @@ -13,14 +13,13 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // - -#include +#include #include #include #include #include -class X: public boost::enable_shared_from_this2< X > +class X: public boost::enable_shared_from_raw { private: @@ -42,7 +41,7 @@ public: explicit X( int expected, boost::shared_ptr *early_px = 0 ): destroyed_( 0 ), deleted_( 0 ), expected_( expected ) { ++instances; - if( early_px ) *early_px = shared_from_this(); + if( early_px ) *early_px = shared_from_raw(this); } ~X() @@ -75,7 +74,7 @@ bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr return !(a < b) && !(b < a); } -struct Y: public boost::enable_shared_from_this2 +struct Y: public boost::enable_shared_from_raw {}; int main() @@ -87,6 +86,7 @@ int main() X* x = new X( 1, &early_px ); BOOST_TEST( early_px.use_count() > 0 ); BOOST_TEST( boost::get_deleter(early_px) == 0 ); + BOOST_TEST( early_px.get() == x ); boost::shared_ptr px( x, &X::deleter2 ); BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 ); BOOST_TEST(are_shared_owners(early_px, px)); @@ -117,7 +117,7 @@ int main() { boost::shared_ptr early_px; - X x( 1, &early_px ); + X x( 2, &early_px ); BOOST_TEST( early_px.use_count() > 0 ); boost::shared_ptr px( &x, &X::deleter ); BOOST_TEST( early_px.use_count() == 2 && px.use_count() == 2 ); @@ -125,13 +125,11 @@ int main() 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 & ) - {} + // test reinitialization after all shared_ptr have expired + early_px = shared_from_raw(&x); + px.reset( &x, &X::deleter ); + BOOST_TEST(are_shared_owners(early_px, px)); + early_px.reset(); } BOOST_TEST( X::instances == 0 ); @@ -157,7 +155,7 @@ int main() px.reset(); try { - y.shared_from_this(); + shared_from_raw(&y); } catch( const boost::bad_weak_ptr & ) {