Index: boost/enable_shared_from_this.hpp =================================================================== --- boost/enable_shared_from_this.hpp (revision 44705) +++ boost/enable_shared_from_this.hpp (working copy) @@ -13,9 +13,11 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html // -#include +#include #include #include +#include +#include #include namespace boost @@ -30,9 +32,9 @@ if( !owned() && _internal_shared_this.get() == 0 ) { T * p = dynamic_cast(const_cast(this)); - _internal_shared_this = shared_ptr( p, detail::sp_deleter_wrapper() ); + _internal_shared_this = shared_ptr( detail::shared_count( p, detail::sp_deleter_wrapper() ), p ); BOOST_ASSERT(_internal_shared_this.get() == this); - _internal_weak_this = _internal_shared_this; + _internal_weak_count = _internal_shared_this._internal_shared_count(); } } @@ -43,7 +45,7 @@ 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 detail::weak_count _internal_weak_count; mutable bool _owned; protected: @@ -77,17 +79,29 @@ shared_ptr shared_from_this() { init_internal_shared_once(); - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; + T * p = dynamic_cast(this); + detail::shared_count c(_internal_weak_count); + if( c.empty() ) + boost::throw_exception( boost::bad_weak_ptr() ); +#if !defined( BOOST_HAS_RVALUE_REFS ) + return shared_ptr(c, p); +#else + return shared_ptr(static_cast< detail::shared_count && >( c ), p); +#endif } shared_ptr shared_from_this() const { init_internal_shared_once(); - shared_ptr p(_internal_weak_this); - BOOST_ASSERT(p.get() == this); - return p; + T const * p = dynamic_cast(this); + detail::shared_count c(_internal_weak_count); + if( c.empty() ) + boost::throw_exception( boost::bad_weak_ptr() ); +#if !defined( BOOST_HAS_RVALUE_REFS ) + return shared_ptr(c, p); +#else + return shared_ptr(static_cast< detail::shared_count && >( c ), p); +#endif } template @@ -97,8 +111,7 @@ { if( !_internal_shared_this ) { - T * p = dynamic_cast(const_cast(this)); - _internal_weak_this = shared_ptr(owner, p); + _internal_weak_count = owner._internal_shared_count(); }else { BOOST_ASSERT(owner.unique()); // no weak_ptrs to owner should exist either, but there's no way to check that @@ -130,10 +143,6 @@ } } -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 Index: boost/detail/shared_count.hpp =================================================================== --- boost/detail/shared_count.hpp (revision 44705) +++ boost/detail/shared_count.hpp (working copy) @@ -25,7 +25,6 @@ #include #include #include -#include #include #include // In order to avoid circular dependencies with Boost.TR1 @@ -49,8 +48,6 @@ #endif -struct sp_nothrow_tag {}; - class weak_count; class shared_count @@ -220,9 +217,20 @@ if( pi_ != 0 ) pi_->add_ref_copy(); } - explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 - shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 +#if defined( BOOST_HAS_RVALUE_REFS ) + shared_count(shared_count && r): pi_(r.pi_) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + r.pi_ = 0; + } + +#endif + + explicit shared_count(weak_count const & r); // nothrow + shared_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; @@ -324,20 +332,28 @@ weak_count & operator= (shared_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } + return *this; } weak_count & operator= (weak_count const & r) // nothrow { sp_counted_base * tmp = r.pi_; - if(tmp != 0) tmp->weak_add_ref(); - if(pi_ != 0) pi_->weak_release(); - pi_ = tmp; + if( tmp != pi_ ) + { + if(tmp != 0) tmp->weak_add_ref(); + if(pi_ != 0) pi_->weak_release(); + pi_ = tmp; + } + return *this; } @@ -369,17 +385,6 @@ , id_(shared_count_id) #endif { - if( pi_ == 0 || !pi_->add_ref_lock() ) - { - boost::throw_exception( boost::bad_weak_ptr() ); - } -} - -inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ) -#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) - , id_(shared_count_id) -#endif -{ if( pi_ != 0 && !pi_->add_ref_lock() ) { pi_ = 0; Index: boost/shared_ptr.hpp =================================================================== --- boost/shared_ptr.hpp (revision 44705) +++ boost/shared_ptr.hpp (working copy) @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -208,19 +209,18 @@ #endif template - explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw + explicit shared_ptr(weak_ptr const & r): pn(r.pn) { - // it is now safe to copy r.px, as pn(r.pn) did not throw + if( pn.empty() ) + boost::throw_exception( boost::bad_weak_ptr() ); + + // it is now safe to copy r.px, as pn is not empty px = r.px; } template - shared_ptr( weak_ptr const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws + shared_ptr(const detail::shared_count & c, Y * p): px(p), pn(c) // never throws { - if( !pn.empty() ) - { - px = r.px; - } } template @@ -354,6 +354,11 @@ return *this; } + template + shared_ptr(detail::shared_count && c, Y * p): px(p), pn( static_cast< detail::shared_count && >( c ) ) // never throws + { + } + #endif void reset() // never throws in 1.30+ @@ -477,6 +482,11 @@ return pn.get_deleter( ti ); } + detail::shared_count const & _internal_shared_count() const // never throws + { + return pn; + } + // atomic access #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) Index: boost/weak_ptr.hpp =================================================================== --- boost/weak_ptr.hpp (revision 44705) +++ boost/weak_ptr.hpp (working copy) @@ -93,7 +93,12 @@ shared_ptr lock() const // never throws { - return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); + detail::shared_count c(pn); +#if !defined( BOOST_HAS_RVALUE_REFS ) + return shared_ptr(c, !c.empty() ? px : 0); +#else + return shared_ptr(static_cast< detail::shared_count && >( c ), !c.empty() ? px : 0); +#endif } long use_count() const // never throws