From 13f91c15f030ebcc1eca28e7bdd4d439b97d4771 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 28 Feb 2009 20:02:12 +0000 Subject: [PATCH] Sync enable_shared_from_this.hpp and shared_ptr.hpp with release. [SVN r51485] --- include/boost/enable_shared_from_this.hpp | 95 +++--------- include/boost/shared_ptr.hpp | 177 +++++++--------------- 2 files changed, 71 insertions(+), 201 deletions(-) diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index b624ee9..4e49f1f 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -13,23 +13,15 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include +#include #include #include -#include +#include namespace boost { -#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - -template< class T > class enable_shared_from_this; -template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); -template< class T, class Y > void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); - -#endif - -template< class T > class enable_shared_from_this +template class enable_shared_from_this { protected: @@ -46,89 +38,36 @@ protected: return *this; } -// virtual destructor because we need a vtable for dynamic_cast from base to derived to work - virtual ~enable_shared_from_this() + ~enable_shared_from_this() { - BOOST_ASSERT( _shared_count.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist } public: shared_ptr shared_from_this() { - init_weak_once(); - T * p = dynamic_cast( this ); - return shared_ptr( detail::shared_count( _weak_count ), p ); + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; } shared_ptr shared_from_this() const { - init_weak_once(); - T const * p = dynamic_cast( this ); - return shared_ptr( detail::shared_count( _weak_count ), p ); + shared_ptr p(_internal_weak_this); + BOOST_ASSERT(p.get() == this); + return p; } -private: +// Note: No, you don't need to initialize _internal_weak_this +// +// Please read the documentation, not the code +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html - mutable detail::weak_count _weak_count; - mutable detail::shared_count _shared_count; - - void init_weak_once() const - { - if( _weak_count.empty() ) - { - detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap( _shared_count ); - _weak_count = _shared_count; - } - } - -#if !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS ) - - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ); - template< class U, class Y > friend void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ); - -#else - -public: - -#endif - - template - void sp_accept_owner( shared_ptr & owner ) const - { - if( _weak_count.use_count() == 0 ) - { - _weak_count = owner.get_shared_count(); - } - else if( !_shared_count.empty() ) - { - BOOST_ASSERT( owner.unique() ); // no weak_ptrs to owner should exist either, but there's no way to check that - detail::sp_deleter_wrapper * pd = detail::basic_get_deleter( _shared_count ); - BOOST_ASSERT( pd != 0 ); - pd->set_deleter( owner.get_shared_count() ); - - owner.reset( _shared_count, owner.get() ); - detail::shared_count().swap( _shared_count ); - } - } + typedef T _internal_element_type; // for bcc 5.5.1 + mutable weak_ptr<_internal_element_type> _internal_weak_this; }; -template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) -{ - if( pe != 0 ) - { - pe->sp_accept_owner( *ptr ); - } -} - -template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe, void * /*pd*/ ) -{ - if( pe != 0 ) - { - pe->sp_accept_owner( *ptr ); - } -} - } // namespace boost #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index e1704ea..ad2bc17 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -58,8 +58,8 @@ namespace boost { -template class shared_ptr; template class weak_ptr; +template class enable_shared_from_this; namespace detail { @@ -98,6 +98,43 @@ template<> struct shared_ptr_traits #endif +// enable_shared_from_this support + +template void sp_enable_shared_from_this( shared_count const & pn, boost::enable_shared_from_this const * pe, Y const * px ) +{ + if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); +} + +#ifdef _MANAGED + +// Avoid C4793, ... causes native code generation + +struct sp_any_pointer +{ + template sp_any_pointer( T* ) {} +}; + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +{ +} + +#else // _MANAGED + +#ifdef sgi +// Turn off: the last argument of the varargs function "sp_enable_shared_from_this" is unnamed +# pragma set woff 3506 +#endif + +inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +{ +} + +#ifdef sgi +# pragma reset woff 3506 +#endif + +#endif // _MANAGED + #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR ) // rvalue auto_ptr support based on a technique by Dave Abrahams @@ -109,38 +146,12 @@ template< class T, class R > struct sp_enable_if_auto_ptr template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R > { typedef R type; -}; +}; #endif } // namespace detail -// sp_accept_owner - -#ifdef _MANAGED - -// Avoid C4793, ... causes native code generation - -struct sp_any_pointer -{ - template sp_any_pointer( T* ) {} -}; - -inline void sp_accept_owner( sp_any_pointer, sp_any_pointer ) -{ -} - -inline void sp_accept_owner( sp_any_pointer, sp_any_pointer, sp_any_pointer ) -{ -} - -#else // _MANAGED - -inline void sp_accept_owner( ... ) -{ -} - -#endif // _MANAGED // // shared_ptr @@ -171,7 +182,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - sp_accept_owner( this, p ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // @@ -180,18 +191,16 @@ public: // shared_ptr will release p by calling d(p) // - template shared_ptr( Y * p, D d ): px( p ), pn( p, d ) + template shared_ptr(Y * p, D d): px(p), pn(p, d) { - D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); - sp_accept_owner( this, p, pd ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // As above, but with allocator. A's copy constructor shall not throw. template shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a ) { - D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); - sp_accept_owner( this, p, pd ); + boost::detail::sp_enable_shared_from_this( pn, p, p ); } // generated copy constructor, assignment, destructor are fine... @@ -238,10 +247,6 @@ public: { } - shared_ptr( detail::shared_count const & c, T * p ): px( p ), pn( c ) // never throws - { - } - // aliasing template< class Y > shared_ptr( shared_ptr const & r, T * p ): px( p ), pn( r.pn ) // never throws @@ -283,8 +288,7 @@ public: { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - - sp_accept_owner( this, tmp ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -294,8 +298,7 @@ public: { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - - sp_accept_owner( this, tmp ); + boost::detail::sp_enable_shared_from_this( pn, tmp, tmp ); } @@ -364,10 +367,6 @@ public: r.px = 0; } - shared_ptr(detail::shared_count && c, T * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws - { - } - shared_ptr & operator=( shared_ptr && r ) // never throws { this_type( static_cast< shared_ptr && >( r ) ).swap( *this ); @@ -409,18 +408,6 @@ public: this_type( r, p ).swap( *this ); } - void reset( detail::shared_count const & c, T * p ) - { - this_type( c, p ).swap( *this ); - } - -#if defined( BOOST_HAS_RVALUE_REFS ) - void reset( detail::shared_count && c, T * p ) - { - this_type( static_cast< detail::shared_count && >( c ), p ).swap( *this ); - } -#endif - reference operator* () const // never throws { BOOST_ASSERT(px != 0); @@ -506,16 +493,16 @@ public: pn.swap(other.pn); } - detail::shared_count const & get_shared_count() const // never throws - { - return pn; - } - template bool _internal_less(shared_ptr const & rhs) const { return pn < rhs.pn; } + void * _internal_get_deleter( detail::sp_typeinfo const & ti ) const + { + return pn.get_deleter( ti ); + } + bool _internal_equiv( shared_ptr const & r ) const { return px == r.px && pn == r.pn; @@ -652,8 +639,6 @@ template std::basic_ostream & operator<< (std:: // get_deleter -namespace detail -{ #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) @@ -661,75 +646,21 @@ namespace detail // g++ 2.9x doesn't allow static_cast(void *) // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it -template D * basic_get_deleter(shared_count const & c) +template D * get_deleter(shared_ptr const & p) { - void const * q = c.get_deleter(BOOST_SP_TYPEID(D)); + void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); return const_cast(static_cast(q)); } #else -template D * basic_get_deleter(shared_count const & c) +template D * get_deleter(shared_ptr const & p) { - return static_cast(c.get_deleter(BOOST_SP_TYPEID(D))); + return static_cast(p._internal_get_deleter(BOOST_SP_TYPEID(D))); } #endif -class sp_deleter_wrapper -{ - detail::shared_count _deleter; -public: - sp_deleter_wrapper() - {} - void set_deleter(shared_count const &deleter) - { - _deleter = deleter; - } - void operator()(const void *) - { - BOOST_ASSERT(_deleter.use_count() <= 1); - detail::shared_count().swap( _deleter ); - } - template -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) - D* get_deleter( D* ) const -#else - D* get_deleter() const -#endif - { - return boost::detail::basic_get_deleter(_deleter); - } -}; - -} // namespace detail - -template D * get_deleter( shared_ptr const & p ) -{ - D *del = detail::basic_get_deleter( p.get_shared_count() ); - - if( del == 0 ) - { - detail::sp_deleter_wrapper *del_wrapper = detail::basic_get_deleter(p.get_shared_count()); - -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 ) - - if( del_wrapper ) del = del_wrapper->get_deleter( (D*)0 ); - -#elif defined( __GNUC__ ) && BOOST_WORKAROUND( __GNUC__, < 4 ) - - if( del_wrapper ) del = del_wrapper->::boost::detail::sp_deleter_wrapper::get_deleter(); - -#else - - if( del_wrapper ) del = del_wrapper->get_deleter(); - -#endif - } - - return del; -} - // atomic access #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)