From a01e4c3f83514c5f0cc933359b31f536f0376876 Mon Sep 17 00:00:00 2001 From: Daniel Frey Date: Sat, 26 Apr 2008 19:59:11 +0000 Subject: [PATCH] Refactored and optimized enable_shared_from_this [SVN r44782] --- include/boost/detail/shared_count.hpp | 5 ++ include/boost/enable_shared_from_this.hpp | 103 ++++++++++------------ 2 files changed, 52 insertions(+), 56 deletions(-) diff --git a/include/boost/detail/shared_count.hpp b/include/boost/detail/shared_count.hpp index e1ca96a..57d1ee9 100644 --- a/include/boost/detail/shared_count.hpp +++ b/include/boost/detail/shared_count.hpp @@ -373,6 +373,11 @@ public: return pi_ != 0? pi_->use_count(): 0; } + bool empty() const // nothrow + { + return pi_ == 0; + } + friend inline bool operator==(weak_count const & a, weak_count const & b) { return a.pi_ == b.pi_; diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index bac9764..c4649af 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -13,7 +13,6 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include #include #include #include @@ -21,35 +20,19 @@ namespace boost { -template class enable_shared_from_this +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*/ ); + +template< class T > class enable_shared_from_this { - void init_internal_shared_once() const - { - if( !owned() && _internal_shared_count.empty() ) - { - detail::shared_count( (void*)0, detail::sp_deleter_wrapper() ).swap(_internal_shared_count); - _internal_weak_count = _internal_shared_count; - } - } - - bool owned() const - { - return _owned; - } - - mutable detail::shared_count _internal_shared_count; - mutable detail::weak_count _internal_weak_count; - mutable bool _owned; - protected: - enable_shared_from_this(): - _owned(false) + enable_shared_from_this() { } - enable_shared_from_this(enable_shared_from_this const &): - _owned(false) + enable_shared_from_this(enable_shared_from_this const &) { } @@ -64,69 +47,77 @@ protected: // 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_count.use_count() <= 1); + BOOST_ASSERT( _shared_count.use_count() <= 1 ); } public: shared_ptr shared_from_this() { - init_internal_shared_once(); - T * p = dynamic_cast(this); - return shared_ptr( detail::shared_count( _internal_weak_count ), p ); + init_weak_once(); + T * p = dynamic_cast( this ); + return shared_ptr( detail::shared_count( _weak_count ), p ); } shared_ptr shared_from_this() const { - init_internal_shared_once(); - T const * p = dynamic_cast(this); - return shared_ptr( detail::shared_count( _internal_weak_count ), p ); + init_weak_once(); + T const * p = dynamic_cast( this ); + return shared_ptr( detail::shared_count( _weak_count ), p ); + } + +private: + + 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; + } } template - void _internal_accept_owner(shared_ptr &owner) const + void sp_accept_owner( shared_ptr & owner ) const { - if( !_owned ) + if( _weak_count.use_count() == 0 ) { - if( _internal_shared_count.empty() ) - { - _internal_weak_count = owner.get_shared_count(); - }else - { - BOOST_ASSERT(owner.unique()); // no weak_ptrs to owner should exist either, but there's no way to check that - typedef detail::sp_deleter_wrapper D; - D * pd = static_cast(_internal_shared_count.get_deleter(BOOST_SP_TYPEID(D))); - BOOST_ASSERT( pd != 0 ); - pd->set_deleter(owner); - - shared_ptr( _internal_shared_count, owner.get() ).swap( owner ); - detail::shared_count().swap(_internal_shared_count); - } - _owned = true; + _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 + typedef detail::sp_deleter_wrapper D; + D * pd = static_cast( _shared_count.get_deleter( BOOST_SP_TYPEID(D) ) ); + BOOST_ASSERT( pd != 0 ); + pd->set_deleter( owner ); + owner.reset( _shared_count, owner.get() ); + detail::shared_count().swap( _shared_count ); } } + + 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*/ ); }; -template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe ) +template< class T, class Y > inline void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) { if( pe != 0 ) { - pe->_internal_accept_owner( *ptr ); + pe->sp_accept_owner( *ptr ); } } -template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe, void * /*pd*/ ) +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->_internal_accept_owner( *ptr ); + pe->sp_accept_owner( *ptr ); } } -template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * /*ptr*/, boost::enable_shared_from_this const * /*pe*/, boost::detail::sp_deleter_wrapper * /*pd*/ ) -{ -} - } // namespace boost #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED