diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index 8e1dd48..1e7d688 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -225,16 +225,35 @@ public: #endif { typedef sp_counted_impl_pda impl_type; + +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + typedef typename std::allocator_traits::template rebind_alloc< impl_type > A2; + +#else + typedef typename A::template rebind< impl_type >::other A2; +#endif + A2 a2( a ); #ifndef BOOST_NO_EXCEPTIONS try { +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + impl_type * pi = std::allocator_traits::allocate( a2, 1 ); + pi_ = pi; + std::allocator_traits::construct( a2, pi, p, d, a ); + +#else + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); - new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + +#endif } catch(...) { @@ -248,13 +267,30 @@ public: throw; } +#else + +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + impl_type * pi = std::allocator_traits::allocate( a2, 1 ); + pi_ = pi; + #else pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); +#endif + if( pi_ != 0 ) { - new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + std::allocator_traits::construct( a2, pi, p, d, a ); + +#else + + ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); + +#endif } else { @@ -273,16 +309,35 @@ public: #endif { typedef sp_counted_impl_pda< P, D, A > impl_type; + +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + typedef typename std::allocator_traits::template rebind_alloc< impl_type > A2; + +#else + typedef typename A::template rebind< impl_type >::other A2; +#endif + A2 a2( a ); #ifndef BOOST_NO_EXCEPTIONS try { +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + impl_type * pi = std::allocator_traits::allocate( a2, 1 ); + pi_ = pi; + std::allocator_traits::construct( a2, pi, p, a ); + +#else + pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); - new( static_cast< void* >( pi_ ) ) impl_type( p, a ); + ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); + +#endif } catch(...) { @@ -296,13 +351,30 @@ public: throw; } +#else + +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + impl_type * pi = std::allocator_traits::allocate( a2, 1 ); + pi_ = pi; + #else pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); +#endif + if( pi_ != 0 ) { - new( static_cast< void* >( pi_ ) ) impl_type( p, a ); +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + std::allocator_traits::construct( a2, pi, p, a ); + +#else + + ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); + +#endif } else { diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp index d15cd3c..404f982 100644 --- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -224,8 +224,16 @@ public: virtual void destroy() // nothrow { +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + typedef typename std::allocator_traits::template rebind_alloc< this_type > A2; + +#else + typedef typename A::template rebind< this_type >::other A2; +#endif + A2 a2( a_ ); this->~this_type(); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 09263d3..d43f696 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -79,6 +79,9 @@ import testing ; [ run sp_zero_compare_test.cpp ] [ run sp_nullptr_test.cpp ] [ run sa_nullptr_test.cpp ] + [ run shared_ptr_alloc3_test.cpp ] + [ run shared_ptr_alloc11_test.cpp ] + [ run allocate_shared_alloc11_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/allocate_shared_alloc11_test.cpp b/test/allocate_shared_alloc11_test.cpp new file mode 100644 index 0000000..bf2a402 --- /dev/null +++ b/test/allocate_shared_alloc11_test.cpp @@ -0,0 +1,241 @@ +// allocate_shared_alloc11_test.cpp +// +// allocate_shared with a minimal C++11 allocator +// +// 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 +#include +#include +#include +#include +#include + +#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 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 ); + } +}; + +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; + + 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; + } +}; + +int X::instances = 0; + +int main() +{ + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator() ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 0 ); + } + + { + boost::shared_ptr< int > pi = boost::allocate_shared< int >( cxx11_allocator(), 5 ); + + BOOST_TEST( pi.get() != 0 ); + BOOST_TEST( *pi == 5 ); + } + + BOOST_TEST( X::instances == 0 ); + + { + boost::shared_ptr< X > pi = boost::allocate_shared< X >( cxx11_allocator() ); + boost::weak_ptr 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(), 1 ); + boost::weak_ptr 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(), 1, 2 ); + boost::weak_ptr 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(), 1, 2, 3 ); + boost::weak_ptr 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(), 1, 2, 3, 4 ); + boost::weak_ptr 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(), 1, 2, 3, 4, 5 ); + boost::weak_ptr 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(), 1, 2, 3, 4, 5, 6 ); + boost::weak_ptr 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(), 1, 2, 3, 4, 5, 6, 7 ); + boost::weak_ptr 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(), 1, 2, 3, 4, 5, 6, 7, 8 ); + boost::weak_ptr 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(), 1, 2, 3, 4, 5, 6, 7, 8, 9 ); + boost::weak_ptr 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 diff --git a/test/shared_ptr_alloc11_test.cpp b/test/shared_ptr_alloc11_test.cpp new file mode 100644 index 0000000..c2b7d6a --- /dev/null +++ b/test/shared_ptr_alloc11_test.cpp @@ -0,0 +1,116 @@ +#include + +// shared_ptr_alloc11_test.cpp +// +// Test the allocator constructor with a C++11 minimal allocator +// +// Copyright (c) 2005, 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 +#include +#include +#include + +#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 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 ); + } +}; + +// + +struct D; + +struct X +{ + static int instances; + + X(): deleted_( false ) + { + ++instances; + } + + ~X() + { + BOOST_TEST( deleted_ ); + --instances; + } + +private: + + friend struct D; + + bool deleted_; + + X( X const & ); + X & operator=( X const & ); +}; + +int X::instances = 0; + +struct D +{ + void operator()( X * px ) const + { + px->deleted_ = true; + delete px; + } +}; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr pv( new X, D(), cxx11_allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + + pv.reset( new X, D(), cxx11_allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +} + +#else // !defined( BOOST_NO_CXX11_ALLOCATOR ) + +int main() +{ + return 0; +} + +#endif diff --git a/test/shared_ptr_alloc2_test.cpp b/test/shared_ptr_alloc2_test.cpp index 93f9d26..89a44bb 100644 --- a/test/shared_ptr_alloc2_test.cpp +++ b/test/shared_ptr_alloc2_test.cpp @@ -91,7 +91,7 @@ public: ::operator delete( p ); } - pointer allocate( size_type n, void const * ) + pointer allocate( size_type n, void const * = 0 ) { T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) ); @@ -107,7 +107,7 @@ public: void construct( pointer p, T const & t ) { - new( p ) T( t ); + ::new( p ) T( t ); } void destroy( pointer p ) diff --git a/test/shared_ptr_alloc3_test.cpp b/test/shared_ptr_alloc3_test.cpp new file mode 100644 index 0000000..011e9cf --- /dev/null +++ b/test/shared_ptr_alloc3_test.cpp @@ -0,0 +1,78 @@ +#include + +// shared_ptr_alloc3_test.cpp +// +// Copyright (c) 2005, 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 +#include +#include +#include + +// + +struct D; + +struct X +{ + static int instances; + + X(): deleted_( false ) + { + ++instances; + } + + ~X() + { + BOOST_TEST( deleted_ ); + --instances; + } + +private: + + friend struct D; + + bool deleted_; + + X( X const & ); + X & operator=( X const & ); +}; + +int X::instances = 0; + +struct D +{ + void operator()( X * px ) const + { + px->deleted_ = true; + delete px; + } +}; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr pv( new X, D(), std::allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + + pv.reset( new X, D(), std::allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +}