Index: boost/enable_shared_from_this.hpp =================================================================== --- boost/enable_shared_from_this.hpp (revision 44344) +++ boost/enable_shared_from_this.hpp (working copy) @@ -29,8 +29,9 @@ { if(owned() == false && _internal_shared_this == 0) { - _internal_shared_this = shared_ptr(dynamic_cast(const_cast(this)), - detail::sp_deleter_wrapper(), detail::ignore_enable_shared_from_this_tag()); + T* p = dynamic_cast(const_cast(this)); + detail::shared_count c(p,detail::sp_deleter_wrapper()); + _internal_shared_this = shared_ptr(c,p); BOOST_ASSERT(_internal_shared_this.get() == this); _internal_weak_this = _internal_shared_this; } @@ -109,6 +110,14 @@ } }; +template void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this const * pe ) +{ + if(pe != 0) + { + pe->_internal_accept_owner(*ptr); + } +} + } // namespace boost #endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED Index: boost/detail/bad_shared_from_this.hpp =================================================================== --- boost/detail/bad_shared_from_this.hpp (revision 0) +++ boost/detail/bad_shared_from_this.hpp (revision 0) @@ -0,0 +1,59 @@ +#ifndef BOOST_BAD_SHARED_FROM_THIS_HPP_INCLUDED +#define BOOST_BAD_SHARED_FROM_THIS_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// detail/bad_shared_from_this.hpp +// +// Copyright (c) 2008 Daniel Frey +// +// 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 + +#ifdef __BORLANDC__ +# pragma warn -8026 // Functions with excep. spec. are not expanded inline +#endif + +namespace boost +{ + +// The standard library that comes with Borland C++ 5.5.1, 5.6.4 +// defines std::exception and its members as having C calling +// convention (-pc). When the definition of bad_shared_from_this +// is compiled with -ps, the compiler issues an error. +// Hence, the temporary #pragma option -pc below. + +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 +# pragma option push -pc +#endif + +class bad_shared_from_this: public std::exception +{ +public: + + virtual char const * what() const throw() + { + return "boost::bad_shared_from_this"; + } +}; + +#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564 +# pragma option pop +#endif + +} // namespace boost + +#ifdef __BORLANDC__ +# pragma warn .8026 // Functions with excep. spec. are not expanded inline +#endif + +#endif // #ifndef BOOST_BAD_SHARED_FROM_THIS_HPP_INCLUDED Index: boost/detail/shared_count.hpp =================================================================== --- boost/detail/shared_count.hpp (revision 44344) +++ boost/detail/shared_count.hpp (working copy) @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -46,8 +45,6 @@ #endif -struct sp_nothrow_tag {}; - class weak_count; class shared_count @@ -218,7 +215,6 @@ } 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 shared_count & operator= (shared_count const & r) // nothrow { @@ -321,20 +317,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; } @@ -366,17 +370,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/weak_ptr.hpp =================================================================== --- boost/weak_ptr.hpp (revision 44344) +++ boost/weak_ptr.hpp (working copy) @@ -93,7 +93,8 @@ shared_ptr lock() const // never throws { - return shared_ptr( *this, boost::detail::sp_nothrow_tag() ); + detail::shared_count c(pn); + return shared_ptr(c, c ? px : 0); } long use_count() const // never throws Index: boost/shared_ptr.hpp =================================================================== --- boost/shared_ptr.hpp (revision 44344) +++ boost/shared_ptr.hpp (working copy) @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,6 @@ template class shared_ptr; template class weak_ptr; -template class enable_shared_from_this; namespace detail { @@ -89,18 +89,8 @@ #endif -// enable_shared_from_this support +// sp_accept_owner support -struct ignore_enable_shared_from_this_tag {}; - -template void sp_enable_shared_from_this( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe ) -{ - if(pe != 0) - { - pe->_internal_accept_owner(*ptr); - } -} - #ifdef _MANAGED // Avoid C4793, ... causes native code generation @@ -110,18 +100,18 @@ template sp_any_pointer( T* ) {} }; -inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer ) +inline void sp_accept_owner( 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 +// Turn off: the last argument of the varargs function "sp_accept_owner" is unnamed # pragma set woff 3506 #endif -inline void sp_enable_shared_from_this( ... ) +inline void sp_accept_owner( ... ) { } @@ -178,7 +168,8 @@ template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - boost::detail::sp_enable_shared_from_this( this, p ); + using detail::sp_accept_owner; + sp_accept_owner( this, p ); } // @@ -189,14 +180,16 @@ template shared_ptr(Y * p, D d): px(p), pn(p, d) { - boost::detail::sp_enable_shared_from_this( this, p ); + using detail::sp_accept_owner; + sp_accept_owner( this, 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 ) { - boost::detail::sp_enable_shared_from_this( this, p ); + using detail::sp_accept_owner; + sp_accept_owner( this, p ); } // generated copy constructor, assignment, destructor are fine... @@ -214,19 +207,19 @@ #endif template - explicit shared_ptr(weak_ptr const & r): pn(r.pn) // may throw + explicit shared_ptr(weak_ptr const & r): pn(r.pn) { + if( pn.empty() ) + boost::throw_exception( boost::bad_weak_ptr() ); + // it is now safe to copy r.px, as pn(r.pn) did not throw 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(detail::shared_count & c, Y * p): px(p) // never throws { - if( !pn.empty() ) - { - px = r.px; - } + pn.swap(c); } template @@ -268,12 +261,6 @@ } } -// constructor that doesn't trigger enable_shared_from_this code, needed -// for enable_shared_from_this internal implementation - template shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag): - px(p), pn(p, d) - {} - #ifndef BOOST_NO_AUTO_PTR template @@ -281,7 +268,8 @@ { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - boost::detail::sp_enable_shared_from_this( this, tmp ); + using detail::sp_accept_owner; + sp_accept_owner( this, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -291,7 +279,8 @@ { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - boost::detail::sp_enable_shared_from_this( this, tmp ); + using detail::sp_accept_owner; + sp_accept_owner( this, tmp ); } @@ -487,6 +476,11 @@ return pn.get_deleter( ti ); } + detail::shared_count const & _internal_shared_count() const // never throws + { + return pn; + } + // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) Index: boost/enable_shared_from_this_light.hpp =================================================================== --- boost/enable_shared_from_this_light.hpp (revision 0) +++ boost/enable_shared_from_this_light.hpp (revision 0) @@ -0,0 +1,77 @@ +#ifndef BOOST_ENABLE_SHARED_FROM_THIS_LIGHT_HPP_INCLUDED +#define BOOST_ENABLE_SHARED_FROM_THIS_LIGHT_HPP_INCLUDED + +// +// enable_shared_from_this_light.hpp +// +// Copyright (c) 2002 Peter Dimov +// Copyright (c) 2008 Daniel Frey +// +// 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) +// +// http://www.boost.org/libs/smart_ptr/enable_shared_from_this_light.html +// + +#include +#include +#include +#include + +namespace boost +{ + +template class enable_shared_from_this_light +{ +protected: + + enable_shared_from_this_light() + { + } + + enable_shared_from_this_light(enable_shared_from_this_light const &) + { + } + + enable_shared_from_this_light & operator=(enable_shared_from_this_light const &) + { + return *this; + } + + ~enable_shared_from_this_light() + { + } + +public: + + shared_ptr shared_from_this() // never throws + { + detail::shared_count c(_internal_weak_count); + if( c.empty() ) + boost::throw_exception( boost::bad_shared_from_this() ); + return shared_ptr(c,static_cast(this)); + } + + shared_ptr shared_from_this() const // never throws + { + detail::shared_count c(_internal_weak_count); + if( c.empty() ) + boost::throw_exception( boost::bad_shared_from_this() ); + return shared_ptr(c,static_cast(this)); + } + + mutable detail::weak_count _internal_weak_count; +}; + +template void sp_accept_owner( shared_ptr * ptr, enable_shared_from_this_light const * pe ) +{ + if(pe != 0) + { + pe->_internal_weak_count = ptr->_internal_shared_count(); + } +} + +} // namespace boost + +#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_LIGHT_HPP_INCLUDED