diff --git a/test/Jamfile b/test/Jamfile index d4cb858..9e92713 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -30,6 +30,7 @@ DEPENDS all : smart_ptr ; [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ run shared_ptr_alloc2_test.cpp ] ; # this one is too slow to run unless explicitly requested, and ALL diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 16c988e..c2237e4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -24,5 +24,6 @@ import testing ; [ run lw_mutex_test.cpp ] [ compile-fail shared_ptr_assign_fail.cpp ] [ compile-fail shared_ptr_delete_fail.cpp ] + [ run shared_ptr_alloc2_test.cpp ] ; } diff --git a/test/shared_ptr_alloc2_test.cpp b/test/shared_ptr_alloc2_test.cpp new file mode 100644 index 0000000..3eb3c46 --- /dev/null +++ b/test/shared_ptr_alloc2_test.cpp @@ -0,0 +1,224 @@ +#include + +// shared_ptr_alloc2_test.cpp +// +// Copyright (c) 2005 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 + +// test_allocator + +struct test_allocator_base +{ + int id_; + + static int last_global_id_; + static int count_; + + explicit test_allocator_base( int id ): id_( id ) + { + } +}; + +int test_allocator_base::last_global_id_ = 0; +int test_allocator_base::count_ = 0; + +template class test_allocator: public test_allocator_base +{ +public: + + typedef T * pointer; + typedef T const * const_pointer; + typedef T & reference; + typedef T const & const_reference; + typedef T value_type; + typedef std::size_t size_type; + typedef ptrdiff_t difference_type; + +private: + + static T * last_pointer_; + static std::size_t last_n_; + static int last_id_; + +public: + + template struct rebind + { + typedef test_allocator other; + }; + + pointer address( reference r ) const + { + return &r; + } + + const_pointer address( const_reference s ) const + { + return &s; + } + + explicit test_allocator( int id = 0 ): test_allocator_base( id ) + { + } + + template test_allocator( test_allocator const & r ): test_allocator_base( r ) + { + } + + template test_allocator & operator=( test_allocator const & r ) + { + test_allocator_base::operator=( r ); + return *this; + } + + void deallocate( pointer p, size_type n ) + { + BOOST_TEST( p == last_pointer_ ); + BOOST_TEST( n == last_n_ ); + BOOST_TEST( id_ == last_id_ ); + + --count_; + + ::operator delete( p ); + } + + pointer allocate( size_type n, void const * ) + { + T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) ); + + last_pointer_ = p; + last_n_ = n; + last_id_ = id_; + + last_global_id_ = id_; + ++count_; + + return p; + } + + void construct( pointer p, T const & t ) + { + new( p ) T( t ); + } + + void destroy( pointer p ) + { + p->~T(); + } + + size_type max_size() const + { + return size_type( -1 ) / sizeof( T ); + } +}; + +template T * test_allocator::last_pointer_ = 0; +template std::size_t test_allocator::last_n_ = 0; +template int test_allocator::last_id_ = 0; + +template inline bool operator==( test_allocator const & a1, test_allocator const & a2 ) +{ + return a1.id_ == a2.id_; +} + +template inline bool operator!=( test_allocator const & a1, test_allocator const & a2 ) +{ + return a1.id_ != a2.id_; +} + +template<> class test_allocator: public test_allocator_base +{ +public: + + typedef void * pointer; + typedef void const * const_pointer; + typedef void value_type; + + template struct rebind + { + typedef test_allocator other; + }; + + explicit test_allocator( int id = 0 ): test_allocator_base( id ) + { + } + + template test_allocator( test_allocator const & r ): test_allocator_base( r ) + { + } + + template test_allocator & operator=( test_allocator const & r ) + { + test_allocator_base::operator=( r ); + return *this; + } +}; + +// + +struct X +{ + static int instances; + + X() + { + ++instances; + } + + ~X() + { + --instances; + } + +private: + + X( X const & ); + X & operator=( X const & ); +}; + +int X::instances = 0; + +int main() +{ + BOOST_TEST( X::instances == 0 ); + + boost::shared_ptr pv( new X, boost::checked_deleter(), std::allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset( new X, boost::checked_deleter(), test_allocator( 42 ) ); + + BOOST_TEST( X::instances == 1 ); + + BOOST_TEST( test_allocator_base::last_global_id_ == 42 ); + BOOST_TEST( test_allocator_base::count_ > 0 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + BOOST_TEST( test_allocator_base::count_ == 0 ); + + pv.reset( new X, boost::checked_deleter(), test_allocator( 43 ) ); + + BOOST_TEST( X::instances == 1 ); + BOOST_TEST( test_allocator_base::last_global_id_ == 43 ); + + pv.reset( new X, boost::checked_deleter(), std::allocator() ); + + BOOST_TEST( X::instances == 1 ); + + pv.reset(); + + BOOST_TEST( X::instances == 0 ); + + return boost::report_errors(); +}