1 #include <boost/config.hpp>
2 
3 //  shared_ptr_alloc2_test.cpp
4 //
5 //  Copyright (c) 2005 Peter Dimov
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See
8 // accompanying file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 
11 
12 #include <boost/detail/lightweight_test.hpp>
13 #include <boost/shared_ptr.hpp>
14 #include <memory>
15 #include <cstddef>
16 
17 // test_allocator
18 
19 struct test_allocator_base
20 {
21     int id_;
22 
23     static int last_global_id_;
24     static int count_;
25 
test_allocator_basetest_allocator_base26     explicit test_allocator_base( int id ): id_( id )
27     {
28     }
29 };
30 
31 int test_allocator_base::last_global_id_ = 0;
32 int test_allocator_base::count_ = 0;
33 
34 template<class T> class test_allocator: public test_allocator_base
35 {
36 public:
37 
38     typedef T * pointer;
39     typedef T const * const_pointer;
40     typedef T & reference;
41     typedef T const & const_reference;
42     typedef T value_type;
43     typedef std::size_t size_type;
44     typedef std::ptrdiff_t difference_type;
45 
46 private:
47 
48     static T * last_pointer_;
49     static std::size_t last_n_;
50     static int last_id_;
51 
52 public:
53 
54     template<class U> struct rebind
55     {
56         typedef test_allocator<U> other;
57     };
58 
address(reference r) const59     pointer address( reference r ) const
60     {
61         return &r;
62     }
63 
address(const_reference s) const64     const_pointer address( const_reference s ) const
65     {
66         return &s;
67     }
68 
test_allocator(int id=0)69     explicit test_allocator( int id = 0 ): test_allocator_base( id )
70     {
71     }
72 
test_allocator(test_allocator<U> const & r)73     template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
74     {
75     }
76 
operator =(test_allocator<U> const & r)77     template<class U> test_allocator & operator=( test_allocator<U> const & r )
78     {
79         test_allocator_base::operator=( r );
80         return *this;
81     }
82 
deallocate(pointer p,size_type n)83     void deallocate( pointer p, size_type n )
84     {
85         BOOST_TEST( p == last_pointer_ );
86         BOOST_TEST( n == last_n_ );
87         BOOST_TEST( id_ == last_id_ );
88 
89         --count_;
90 
91         ::operator delete( p );
92     }
93 
allocate(size_type n,void const * =0)94     pointer allocate( size_type n, void const * = 0 )
95     {
96         T * p = static_cast< T* >( ::operator new( n * sizeof( T ) ) );
97 
98         last_pointer_ = p;
99         last_n_ = n;
100         last_id_ = id_;
101 
102         last_global_id_ = id_;
103         ++count_;
104 
105         return p;
106     }
107 
construct(pointer p,T const & t)108     void construct( pointer p, T const & t )
109     {
110         ::new( p ) T( t );
111     }
112 
destroy(pointer p)113     void destroy( pointer p )
114     {
115         p->~T();
116     }
117 
max_size() const118     size_type max_size() const
119     {
120         return size_type( -1 ) / sizeof( T );
121     }
122 };
123 
124 template<class T> T * test_allocator<T>::last_pointer_ = 0;
125 template<class T> std::size_t test_allocator<T>::last_n_ = 0;
126 template<class T> int test_allocator<T>::last_id_ = 0;
127 
operator ==(test_allocator<T> const & a1,test_allocator<U> const & a2)128 template<class T, class U> inline bool operator==( test_allocator<T> const & a1, test_allocator<U> const & a2 )
129 {
130     return a1.id_ == a2.id_;
131 }
132 
operator !=(test_allocator<T> const & a1,test_allocator<U> const & a2)133 template<class T, class U> inline bool operator!=( test_allocator<T> const & a1, test_allocator<U> const & a2 )
134 {
135     return a1.id_ != a2.id_;
136 }
137 
138 template<> class test_allocator<void>: public test_allocator_base
139 {
140 public:
141 
142     typedef void * pointer;
143     typedef void const * const_pointer;
144     typedef void value_type;
145 
146     template<class U> struct rebind
147     {
148         typedef test_allocator<U> other;
149     };
150 
test_allocator(int id=0)151     explicit test_allocator( int id = 0 ): test_allocator_base( id )
152     {
153     }
154 
test_allocator(test_allocator<U> const & r)155     template<class U> test_allocator( test_allocator<U> const & r ): test_allocator_base( r )
156     {
157     }
158 
operator =(test_allocator<U> const & r)159     template<class U> test_allocator & operator=( test_allocator<U> const & r )
160     {
161         test_allocator_base::operator=( r );
162         return *this;
163     }
164 };
165 
166 //
167 
168 struct X
169 {
170     static int instances;
171 
XX172     X()
173     {
174         ++instances;
175     }
176 
~XX177     ~X()
178     {
179         --instances;
180     }
181 
182 private:
183 
184     X( X const & );
185     X & operator=( X const & );
186 };
187 
188 int X::instances = 0;
189 
main()190 int main()
191 {
192     BOOST_TEST( X::instances == 0 );
193 
194     boost::shared_ptr<void> pv( new X, boost::checked_deleter<X>(), std::allocator<X>() );
195 
196     BOOST_TEST( X::instances == 1 );
197 
198     pv.reset( new X, boost::checked_deleter<X>(), test_allocator<float>( 42 ) );
199 
200     BOOST_TEST( X::instances == 1 );
201 
202     BOOST_TEST( test_allocator_base::last_global_id_ == 42 );
203     BOOST_TEST( test_allocator_base::count_ > 0 );
204 
205     pv.reset();
206 
207     BOOST_TEST( X::instances == 0 );
208     BOOST_TEST( test_allocator_base::count_ == 0 );
209 
210     pv.reset( new X, boost::checked_deleter<X>(), test_allocator<void>( 43 ) );
211 
212     BOOST_TEST( X::instances == 1 );
213     BOOST_TEST( test_allocator_base::last_global_id_ == 43 );
214 
215     pv.reset( new X, boost::checked_deleter<X>(), std::allocator<void>() );
216 
217     BOOST_TEST( X::instances == 1 );
218 
219     pv.reset();
220 
221     BOOST_TEST( X::instances == 0 );
222 
223     return boost::report_errors();
224 }
225