mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-07-30 04:47:12 +02:00
Add support and test for C++11 construct/destroy in allocate_shared
This commit is contained in:
@ -213,7 +213,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
sp_counted_impl_pda( P p, A a ): p_( p ), d_(), a_( a )
|
||||
sp_counted_impl_pda( P p, A a ): p_( p ), d_( a ), a_( a )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template<class A> explicit sp_ms_deleter( A const & ) BOOST_NOEXCEPT : initialized_( false )
|
||||
{
|
||||
}
|
||||
|
||||
// optimization: do not copy storage_
|
||||
sp_ms_deleter( sp_ms_deleter const & ) BOOST_NOEXCEPT : initialized_( false )
|
||||
{
|
||||
@ -102,6 +106,74 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template< class T, class A > class sp_as_deleter
|
||||
{
|
||||
private:
|
||||
|
||||
typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
|
||||
|
||||
storage_type storage_;
|
||||
A a_;
|
||||
bool initialized_;
|
||||
|
||||
private:
|
||||
|
||||
void destroy()
|
||||
{
|
||||
if( initialized_ )
|
||||
{
|
||||
T * p = reinterpret_cast< T* >( storage_.data_ );
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
std::allocator_traits<A>::destroy( a_, p );
|
||||
|
||||
#else
|
||||
|
||||
p->~T();
|
||||
|
||||
#endif
|
||||
|
||||
initialized_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
sp_as_deleter( A const & a ) BOOST_NOEXCEPT : a_( a ), initialized_( false )
|
||||
{
|
||||
}
|
||||
|
||||
// optimization: do not copy storage_
|
||||
sp_as_deleter( sp_as_deleter const & r ) BOOST_NOEXCEPT : a_( r.a_), initialized_( false )
|
||||
{
|
||||
}
|
||||
|
||||
~sp_as_deleter()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void operator()( T * )
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
static void operator_fn( T* ) // operator() can't be static
|
||||
{
|
||||
}
|
||||
|
||||
void * address() BOOST_NOEXCEPT
|
||||
{
|
||||
return storage_.data_;
|
||||
}
|
||||
|
||||
void set_initialized() BOOST_NOEXCEPT
|
||||
{
|
||||
initialized_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
template< class T > struct sp_if_not_array
|
||||
{
|
||||
typedef boost::shared_ptr< T > type;
|
||||
@ -190,13 +262,36 @@ template< class T, class... Args > typename boost::detail::sp_if_not_array< T >:
|
||||
|
||||
template< class T, class A, class... Args > typename boost::detail::sp_if_not_array< T >::type allocate_shared( A const & a, Args && ... args )
|
||||
{
|
||||
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), BOOST_SP_MSD( T ), a );
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
boost::detail::sp_ms_deleter< T > * pd = static_cast<boost::detail::sp_ms_deleter< T > *>( pt._internal_get_untyped_deleter() );
|
||||
typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
|
||||
A2 a2( a );
|
||||
|
||||
typedef boost::detail::sp_as_deleter< T, A2 > D;
|
||||
|
||||
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
|
||||
|
||||
#else
|
||||
|
||||
typedef boost::detail::sp_ms_deleter< T > D;
|
||||
|
||||
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a );
|
||||
|
||||
#endif
|
||||
|
||||
D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
|
||||
void * pv = pd->address();
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), boost::detail::sp_forward<Args>( args )... );
|
||||
|
||||
#else
|
||||
|
||||
::new( pv ) T( boost::detail::sp_forward<Args>( args )... );
|
||||
|
||||
#endif
|
||||
|
||||
pd->set_initialized();
|
||||
|
||||
T * pt2 = static_cast< T* >( pv );
|
||||
|
@ -82,6 +82,7 @@ import testing ;
|
||||
[ run shared_ptr_alloc3_test.cpp ]
|
||||
[ run shared_ptr_alloc11_test.cpp ]
|
||||
[ run allocate_shared_alloc11_test.cpp ]
|
||||
[ run allocate_shared_construct11_test.cpp ]
|
||||
|
||||
[ compile-fail array_fail_spa_sp_c.cpp ]
|
||||
[ compile-fail array_fail_sp_spa_c.cpp ]
|
||||
|
240
test/allocate_shared_construct11_test.cpp
Normal file
240
test/allocate_shared_construct11_test.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
// allocate_shared_construct11_test.cpp
|
||||
//
|
||||
// Test whether allocate_shared uses construct/destroy in C++11
|
||||
//
|
||||
// Copyright 2007-2009, 2014 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/detail/lightweight_test.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
template< class T > class cxx11_allocator
|
||||
{
|
||||
public:
|
||||
|
||||
typedef T value_type;
|
||||
|
||||
cxx11_allocator()
|
||||
{
|
||||
}
|
||||
|
||||
template< class Y > cxx11_allocator( cxx11_allocator<Y> const & )
|
||||
{
|
||||
}
|
||||
|
||||
T * allocate( std::size_t n )
|
||||
{
|
||||
return static_cast< T* >( ::operator new( n * sizeof( T ) ) );
|
||||
}
|
||||
|
||||
void deallocate( T * p, std::size_t n )
|
||||
{
|
||||
::operator delete( p );
|
||||
}
|
||||
|
||||
template<class... Args> void construct( T * p, Args&&... args )
|
||||
{
|
||||
::new( static_cast< void* >( p ) ) T( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
void destroy( T * p )
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
};
|
||||
|
||||
class X
|
||||
{
|
||||
private:
|
||||
|
||||
X( X const & );
|
||||
X & operator=( X const & );
|
||||
|
||||
void * operator new( std::size_t n )
|
||||
{
|
||||
BOOST_ERROR( "private X::new called" );
|
||||
return ::operator new( n );
|
||||
}
|
||||
|
||||
void operator delete( void * p )
|
||||
{
|
||||
BOOST_ERROR( "private X::delete called" );
|
||||
::operator delete( p );
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static int instances;
|
||||
|
||||
int v;
|
||||
|
||||
protected:
|
||||
|
||||
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
|
||||
{
|
||||
++instances;
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
--instances;
|
||||
}
|
||||
|
||||
friend class cxx11_allocator<X>;
|
||||
};
|
||||
|
||||
int X::instances = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>() );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 0 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2+3 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2+3+4 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2+3+4+5 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
|
||||
boost::weak_ptr<X> wp( pi );
|
||||
|
||||
BOOST_TEST( X::instances == 1 );
|
||||
BOOST_TEST( pi.get() != 0 );
|
||||
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
|
||||
|
||||
pi.reset();
|
||||
|
||||
BOOST_TEST( X::instances == 0 );
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else // !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user