mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-08-01 21:54:28 +02:00
sp_accept_owner added.
[SVN r44353]
This commit is contained in:
@@ -27,10 +27,10 @@ template<class T> class enable_shared_from_this
|
|||||||
// to use lazy initialization
|
// to use lazy initialization
|
||||||
void init_internal_shared_once() const
|
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)),
|
T * p = dynamic_cast<T *>(const_cast<enable_shared_from_this*>(this));
|
||||||
detail::sp_deleter_wrapper(), detail::ignore_enable_shared_from_this_tag());
|
_internal_shared_this = shared_ptr<T>( p, detail::sp_deleter_wrapper() );
|
||||||
BOOST_ASSERT(_internal_shared_this.get() == this);
|
BOOST_ASSERT(_internal_shared_this.get() == this);
|
||||||
_internal_weak_this = _internal_shared_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
|
} // namespace boost
|
||||||
|
|
||||||
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
|
||||||
|
@@ -50,7 +50,6 @@ namespace boost
|
|||||||
|
|
||||||
template<class T> class shared_ptr;
|
template<class T> class shared_ptr;
|
||||||
template<class T> class weak_ptr;
|
template<class T> class weak_ptr;
|
||||||
template<class T> class enable_shared_from_this;
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@@ -89,48 +88,6 @@ template<> struct shared_ptr_traits<void const volatile>
|
|||||||
|
|
||||||
#endif
|
#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 )
|
#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
|
// 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
|
} // 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
|
// shared_ptr
|
||||||
@@ -178,7 +161,7 @@ public:
|
|||||||
template<class Y>
|
template<class Y>
|
||||||
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
|
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)
|
// 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.
|
// 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 )
|
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...
|
// 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
|
#ifndef BOOST_NO_AUTO_PTR
|
||||||
|
|
||||||
template<class Y>
|
template<class Y>
|
||||||
@@ -281,7 +260,8 @@ public:
|
|||||||
{
|
{
|
||||||
Y * tmp = r.get();
|
Y * tmp = r.get();
|
||||||
pn = boost::detail::shared_count(r);
|
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 )
|
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
|
||||||
@@ -291,7 +271,8 @@ public:
|
|||||||
{
|
{
|
||||||
typename Ap::element_type * tmp = r.get();
|
typename Ap::element_type * tmp = r.get();
|
||||||
pn = boost::detail::shared_count( r );
|
pn = boost::detail::shared_count( r );
|
||||||
boost::detail::sp_enable_shared_from_this( this, tmp );
|
|
||||||
|
sp_accept_owner( this, tmp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -43,5 +43,6 @@ import testing ;
|
|||||||
[ run spinlock_try_test.cpp ]
|
[ run spinlock_try_test.cpp ]
|
||||||
[ run spinlock_try_test.cpp : : : <threading>multi : spinlock_try_test.mt ]
|
[ run spinlock_try_test.cpp : : : <threading>multi : spinlock_try_test.mt ]
|
||||||
[ run spinlock_pool_test.cpp ]
|
[ run spinlock_pool_test.cpp ]
|
||||||
|
[ run sp_accept_owner_test.cpp ]
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@@ -72,7 +72,7 @@ int X::instances = 0;
|
|||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
bool are_shared_owners(const boost::shared_ptr<T> &a, const boost::shared_ptr<U> &b)
|
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>
|
struct Y: public boost::enable_shared_from_this<Y>
|
||||||
|
146
test/sp_accept_owner_test.cpp
Normal file
146
test/sp_accept_owner_test.cpp
Normal 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();
|
||||||
|
}
|
Reference in New Issue
Block a user