sp_accept_owner added.

[SVN r44353]
This commit is contained in:
Peter Dimov
2008-04-12 18:22:18 +00:00
parent f85a1bf406
commit 4094c23537
5 changed files with 207 additions and 59 deletions

View File

@ -27,10 +27,10 @@ template<class T> 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<T>(dynamic_cast<T *>(const_cast<enable_shared_from_this*>(this)),
detail::sp_deleter_wrapper(), detail::ignore_enable_shared_from_this_tag());
T * p = dynamic_cast<T *>(const_cast<enable_shared_from_this*>(this));
_internal_shared_this = shared_ptr<T>( 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<Y> * ptr, boost::enable_shared_from_this<T> const * pe )
{
if( pe != 0 )
{
pe->_internal_accept_owner( *ptr );
}
}
template< class T, class Y > inline void sp_accept_owner( boost::shared_ptr<Y> * ptr, boost::enable_shared_from_this<T> 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<Y> * /*ptr*/, boost::enable_shared_from_this<T> const * /*pe*/, boost::detail::sp_deleter_wrapper * /*pd*/ )
{
}
} // namespace boost
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED

View File

@ -50,7 +50,6 @@ namespace boost
template<class T> class shared_ptr;
template<class T> class weak_ptr;
template<class T> class enable_shared_from_this;
namespace detail
{
@ -89,48 +88,6 @@ template<> struct shared_ptr_traits<void const volatile>
#endif
// enable_shared_from_this support
struct ignore_enable_shared_from_this_tag {};
template<class T, class Y> void sp_enable_shared_from_this( boost::shared_ptr<Y> * ptr, boost::enable_shared_from_this<T> const * pe )
{
if(pe != 0)
{
pe->_internal_accept_owner(*ptr);
}
}
#ifdef _MANAGED
// Avoid C4793, ... causes native code generation
struct sp_any_pointer
{
template<class T> 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<class T> 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<class Y>
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<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
{
boost::detail::sp_enable_shared_from_this( this, p );
D * pd = static_cast<D *>( 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<class Y, class D, class A> 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<D *>( 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<class Y, class D> shared_ptr(Y * p, D d, detail::ignore_enable_shared_from_this_tag):
px(p), pn(p, d)
{}
#ifndef BOOST_NO_AUTO_PTR
template<class Y>
@ -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 );
}

View File

@ -43,5 +43,6 @@ import testing ;
[ run spinlock_try_test.cpp ]
[ run spinlock_try_test.cpp : : : <threading>multi : spinlock_try_test.mt ]
[ run spinlock_pool_test.cpp ]
[ run sp_accept_owner_test.cpp ]
;
}

View File

@ -72,7 +72,7 @@ int X::instances = 0;
template<typename T, typename U>
bool are_shared_owners(const boost::shared_ptr<T> &a, const boost::shared_ptr<U> &b)
{
return a && !(a < b) && !(b < a);
return !(a < b) && !(b < a);
}
struct Y: public boost::enable_shared_from_this<Y>

View File

@ -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 <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
namespace N
{
struct D;
struct X
{
X * px_;
D * pd_;
void * pv_;
X(): px_( 0 ), pd_( 0 ), pv_( 0 )
{
}
};
struct D
{
template<class T> void operator()( T * p ) const { delete p; }
};
} // namespace N
#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP )
namespace N
{
#else
namespace boost
{
#endif
template<class Y> inline void sp_accept_owner( boost::shared_ptr<Y> * ps, ::N::X * px )
{
std::cout << "sp_accept_owner( " << ps << ", " << px << " )\n";
BOOST_TEST( ps->get() == px );
if( px != 0 )
{
px->px_ = px;
}
}
template<class Y> inline void sp_accept_owner( boost::shared_ptr<Y> * 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<class Y> inline void sp_accept_owner( boost::shared_ptr<Y> * 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<class T> void operator()( T * p ) const { delete p; }
};
template<class T> void test( T* = 0 )
{
{
boost::shared_ptr<T> p( static_cast< T* >( 0 ) );
}
{
T * p = new T;
boost::shared_ptr<T> q( p );
BOOST_TEST( q->px_ == p );
BOOST_TEST( q->pd_ == 0 );
BOOST_TEST( q->pv_ == 0 );
}
{
T * p = new T;
boost::shared_ptr<T> 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<T> 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<N::X>();
test<N2::Y>();
return boost::report_errors();
}