mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-07-31 05:07:21 +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
|
||||
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
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 ]
|
||||
;
|
||||
}
|
||||
|
@ -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>
|
||||
|
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