From 4094c2353733dfd9fe568f642d701cce994cdedb Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Apr 2008 18:22:18 +0000 Subject: [PATCH] sp_accept_owner added. [SVN r44353] --- include/boost/enable_shared_from_this.hpp | 26 +++- include/boost/shared_ptr.hpp | 91 ++++++-------- test/Jamfile.v2 | 1 + test/esft_constructor_test.cpp | 2 +- test/sp_accept_owner_test.cpp | 146 ++++++++++++++++++++++ 5 files changed, 207 insertions(+), 59 deletions(-) create mode 100644 test/sp_accept_owner_test.cpp diff --git a/include/boost/enable_shared_from_this.hpp b/include/boost/enable_shared_from_this.hpp index 2ead3fd..23ec297 100644 --- a/include/boost/enable_shared_from_this.hpp +++ b/include/boost/enable_shared_from_this.hpp @@ -27,10 +27,10 @@ template class enable_shared_from_this // to use lazy initialization void init_internal_shared_once() const { - if(owned() == false && _internal_shared_this == 0) + if( !owned() && _internal_shared_this.get() == 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)); + _internal_shared_this = shared_ptr( p, detail::sp_deleter_wrapper() ); BOOST_ASSERT(_internal_shared_this.get() == this); _internal_weak_this = _internal_shared_this; } @@ -109,6 +109,26 @@ public: } }; +template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr * ptr, boost::enable_shared_from_this const * pe ) +{ + if( pe != 0 ) + { + pe->_internal_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*/ ) +{ + if( pe != 0 ) + { + pe->_internal_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 diff --git a/include/boost/shared_ptr.hpp b/include/boost/shared_ptr.hpp index 4b23ec1..2c9c3e6 100644 --- a/include/boost/shared_ptr.hpp +++ b/include/boost/shared_ptr.hpp @@ -50,7 +50,6 @@ namespace boost template class shared_ptr; template class weak_ptr; -template class enable_shared_from_this; namespace detail { @@ -89,48 +88,6 @@ template<> struct shared_ptr_traits #endif -// enable_shared_from_this 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 - -struct sp_any_pointer -{ - template sp_any_pointer( T* ) {} -}; - -inline void sp_enable_shared_from_this( 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( ... ) -{ -} - -#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 @@ -148,6 +105,32 @@ template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R } // 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 @@ -178,7 +161,7 @@ public: template explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete { - boost::detail::sp_enable_shared_from_this( this, p ); + sp_accept_owner( this, p ); } // @@ -187,16 +170,18 @@ 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 ) { - boost::detail::sp_enable_shared_from_this( this, p ); + D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); + sp_accept_owner( this, p, pd ); } // 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 ); + D * pd = static_cast( pn.get_deleter( BOOST_SP_TYPEID(D) ) ); + sp_accept_owner( this, p, pd ); } // generated copy constructor, assignment, destructor are fine... @@ -268,12 +253,6 @@ public: } } -// 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 +260,8 @@ public: { Y * tmp = r.get(); pn = boost::detail::shared_count(r); - boost::detail::sp_enable_shared_from_this( this, tmp ); + + sp_accept_owner( this, tmp ); } #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) @@ -291,7 +271,8 @@ public: { typename Ap::element_type * tmp = r.get(); pn = boost::detail::shared_count( r ); - boost::detail::sp_enable_shared_from_this( this, tmp ); + + sp_accept_owner( this, tmp ); } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0ccc984..499f9b9 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -43,5 +43,6 @@ import testing ; [ run spinlock_try_test.cpp ] [ run spinlock_try_test.cpp : : : multi : spinlock_try_test.mt ] [ run spinlock_pool_test.cpp ] + [ run sp_accept_owner_test.cpp ] ; } diff --git a/test/esft_constructor_test.cpp b/test/esft_constructor_test.cpp index 068f236..737123e 100644 --- a/test/esft_constructor_test.cpp +++ b/test/esft_constructor_test.cpp @@ -72,7 +72,7 @@ int X::instances = 0; template bool are_shared_owners(const boost::shared_ptr &a, const boost::shared_ptr &b) { - return a && !(a < b) && !(b < a); + return !(a < b) && !(b < a); } struct Y: public boost::enable_shared_from_this diff --git a/test/sp_accept_owner_test.cpp b/test/sp_accept_owner_test.cpp new file mode 100644 index 0000000..e8d1b32 --- /dev/null +++ b/test/sp_accept_owner_test.cpp @@ -0,0 +1,146 @@ +// +// sp_accept_owner_test.cpp +// +// Copyright (c) 2008 Peter Dimov +// +// 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 +#include +#include + +namespace N +{ + +struct D; + +struct X +{ + X * px_; + + D * pd_; + void * pv_; + + X(): px_( 0 ), pd_( 0 ), pv_( 0 ) + { + } +}; + +struct D +{ + template void operator()( T * p ) const { delete p; } +}; + +} // namespace N + +#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) + +namespace N +{ + +#else + +namespace boost +{ + +#endif + +template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px ) +{ + std::cout << "sp_accept_owner( " << ps << ", " << px << " )\n"; + + BOOST_TEST( ps->get() == px ); + + if( px != 0 ) + { + px->px_ = px; + } +} + +template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px, ::N::D * pd ) +{ + std::cout << "sp_accept_owner( " << ps << ", " << px << ", (D*)" << pd << " )\n"; + + BOOST_TEST( ps->get() == px ); + + if( px != 0 ) + { + px->px_ = px; + px->pd_ = pd; + } +} + +template inline void sp_accept_owner( boost::shared_ptr * ps, ::N::X * px, void * pv ) +{ + std::cout << "sp_accept_owner( " << ps << ", " << px << ", (void*)" << pv << " )\n"; + + BOOST_TEST( ps->get() == px ); + + if( px != 0 ) + { + px->px_ = px; + px->pv_ = pv; + } +} + +} // namespace N or boost + +struct D2 +{ + template void operator()( T * p ) const { delete p; } +}; + +template void test( T* = 0 ) +{ + { + boost::shared_ptr p( static_cast< T* >( 0 ) ); + } + + { + T * p = new T; + boost::shared_ptr q( p ); + + BOOST_TEST( q->px_ == p ); + BOOST_TEST( q->pd_ == 0 ); + BOOST_TEST( q->pv_ == 0 ); + } + + { + T * p = new T; + boost::shared_ptr q( p, N::D() ); + + BOOST_TEST( q->px_ == p ); + BOOST_TEST( q->pd_ != 0 ); + BOOST_TEST( q->pv_ == 0 ); + } + + { + T * p = new T; + boost::shared_ptr q( p, D2() ); + + BOOST_TEST( q->px_ == p ); + BOOST_TEST( q->pd_ == 0 ); + BOOST_TEST( q->pv_ != 0 ); + } +} + +namespace N2 +{ + +struct Y: public virtual N::X +{ +}; + +} // namespace N2 + +int main() +{ + test(); + test(); + + return boost::report_errors(); +}