Index: boost/enable_shared_from_this.hpp =================================================================== --- boost/enable_shared_from_this.hpp (revision 43677) +++ boost/enable_shared_from_this.hpp (working copy) @@ -23,9 +23,21 @@ template class enable_shared_from_this { + void init_internal_shared_once() const + { + if(_owned == false && _internal_shared_this == 0) + { + _internal_shared_this = shared_ptr(dynamic_cast(const_cast(this)), + &_internal_shared_this_deleter, detail::ignore_shared_from_this_tag()); + BOOST_ASSERT(_internal_shared_this.get() == this); + _internal_weak_this = _internal_shared_this; + } + } + protected: - enable_shared_from_this() + enable_shared_from_this(): + _owned(false) { } @@ -38,7 +50,7 @@ return *this; } - ~enable_shared_from_this() + virtual ~enable_shared_from_this() { } @@ -46,6 +58,7 @@ shared_ptr shared_from_this() { + init_internal_shared_once(); shared_ptr p(_internal_weak_this); BOOST_ASSERT(p.get() == this); return p; @@ -53,11 +66,27 @@ shared_ptr shared_from_this() const { + init_internal_shared_once(); shared_ptr p(_internal_weak_this); BOOST_ASSERT(p.get() == this); return p; } + bool owned() const + { + return _owned; + } + + void _internal_set_user_deleter(const detail::shared_count &user_deleter) const + { + init_internal_shared_once(); + _user_deleter = user_deleter; + } + static void _internal_shared_this_deleter(const enable_shared_from_this *obj) + { + detail::shared_count().swap(obj->_user_deleter); + } + // Note: No, you don't need to initialize _internal_weak_this // // Please read the documentation, not the code @@ -65,7 +94,10 @@ // http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html typedef T _internal_element_type; // for bcc 5.5.1 + mutable shared_ptr<_internal_element_type> _internal_shared_this; + mutable detail::shared_count _user_deleter; mutable weak_ptr<_internal_element_type> _internal_weak_this; + mutable bool _owned; }; } // namespace boost Index: boost/shared_ptr.hpp =================================================================== --- boost/shared_ptr.hpp (revision 43677) +++ boost/shared_ptr.hpp (working copy) @@ -90,10 +90,18 @@ // 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 ) +struct ignore_shared_from_this_tag {}; + +template void sp_enable_shared_from_this( shared_count & pn, boost::enable_shared_from_this const * pe, Y const * px) { - if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast(px), pn); + if(pe != 0) + { + pe->_internal_set_user_deleter(pn); + pn.swap(pe->_internal_shared_this.pn); + pe->_internal_shared_this.reset(); + pe->_owned = true; } +} #ifdef _MANAGED @@ -104,7 +112,7 @@ template sp_any_pointer( T* ) {} }; -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, sp_any_pointer, sp_any_pointer ) +inline void sp_enable_shared_from_this( shared_count & /*pn*/, sp_any_pointer, sp_any_pointer ) { } @@ -115,7 +123,7 @@ # pragma set woff 3506 #endif -inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... ) +inline void sp_enable_shared_from_this( shared_count & /*pn*/, ... ) { } @@ -186,6 +194,13 @@ boost::detail::sp_enable_shared_from_this( pn, p, p ); } + // 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_shared_from_this_tag tag): + px(p), pn(p, d) + {} + + // 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 ) @@ -480,6 +495,8 @@ #endif T * px; // contained pointer +/*yikes! made pn public to get this hack working */ +public: boost::detail::shared_count pn; // reference counter }; // shared_ptr