Add support and test for C++11 construct/destroy in allocate_shared

This commit is contained in:
Peter Dimov committed 2014-02-05 02:31:33 +02:00
1 parent d229ae870c
commit 9f5822f427
4 files changed
+339 -3

No files matched your search

@@ -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 )
{
}
+97 -2
View File
@@ -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 );