1 /* Copyright (C) 2000, 2001 Stephen Cleary
2 * Copyright (C) 2011 Kwan Ting Chan
4 * Use, modification and distribution is subject to the
5 * Boost Software License, Version 1.0. (See accompanying
6 * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
9 #include "random_shuffle.hpp"
10 #include <boost/pool/pool_alloc.hpp>
11 #include <boost/pool/object_pool.hpp>
13 #include <boost/detail/lightweight_test.hpp>
25 // Each "tester" object below checks into and out of the "cdtor_checker",
26 // which will check for any problems related to the construction/destruction of
31 // Each constructed object registers its "this" pointer into "objs"
35 // True iff all objects that have checked in have checked out
36 bool ok() const { return objs
.empty(); }
43 void check_in(void * const This
)
45 BOOST_TEST(objs
.find(This
) == objs
.end());
49 void check_out(void * const This
)
51 BOOST_TEST(objs
.find(This
) != objs
.end());
55 static cdtor_checker mem
;
59 tester(bool throw_except
= false)
63 throw std::logic_error("Deliberate constructor exception");
69 tester(const tester
&)
80 // This is a wrapper around a UserAllocator. It just registers alloc/dealloc
81 // to/from the system memory. It's used to make sure pool's are allocating
82 // and deallocating system memory properly.
83 // Do NOT use this class with static or singleton pools.
84 template <typename UserAllocator
>
87 typedef typename
UserAllocator::size_type size_type
;
88 typedef typename
UserAllocator::difference_type difference_type
;
90 static std::set
<char *> allocated_blocks
;
92 static char * malloc(const size_type bytes
)
94 char * const ret
= UserAllocator::malloc(bytes
);
95 allocated_blocks
.insert(ret
);
99 static void free(char * const block
)
101 BOOST_TEST(allocated_blocks
.find(block
) != allocated_blocks
.end());
102 allocated_blocks
.erase(block
);
103 UserAllocator::free(block
);
108 return allocated_blocks
.empty();
111 template <typename UserAllocator
>
112 std::set
<char *> TrackAlloc
<UserAllocator
>::allocated_blocks
;
114 typedef TrackAlloc
<boost::default_user_allocator_new_delete
> track_alloc
;
120 boost::object_pool
<tester
> pool
;
124 // Construct several tester objects. Don't delete them (i.e.,
125 // test pool's garbage collection).
126 boost::object_pool
<tester
> pool
;
127 for(int i
=0; i
< 10; ++i
)
134 // Construct several tester objects. Delete some of them.
135 boost::object_pool
<tester
> pool
;
136 std::vector
<tester
*> v
;
137 for(int i
=0; i
< 10; ++i
)
139 v
.push_back(pool
.construct());
141 pool_test_random_shuffle(v
.begin(), v
.end());
142 for(int j
=0; j
< 5; ++j
)
149 // Test how pool reacts with constructors that throw exceptions.
150 // Shouldn't have any memory leaks.
151 boost::object_pool
<tester
> pool
;
152 for(int i
=0; i
< 5; ++i
)
156 for(int j
=0; j
< 5; ++j
)
160 // The following constructions will raise an exception.
161 pool
.construct(true);
163 catch(const std::logic_error
&) {}
171 // Allocate several tester objects. Delete one.
172 std::vector
<tester
, boost::pool_allocator
<tester
> > l
;
173 for(int i
=0; i
< 10; ++i
)
175 l
.push_back(tester());
181 // Allocate several tester objects. Delete two.
182 std::deque
<tester
, boost::pool_allocator
<tester
> > l
;
183 for(int i
=0; i
< 10; ++i
)
185 l
.push_back(tester());
192 // Allocate several tester objects. Delete two.
193 std::list
<tester
, boost::fast_pool_allocator
<tester
> > l
;
194 // lists rebind their allocators, so dumping is useless
195 for(int i
=0; i
< 10; ++i
)
197 l
.push_back(tester());
205 // Create a memory leak on purpose. (Allocator doesn't have
206 // garbage collection)
207 // (Note: memory leak)
208 boost::pool_allocator
<tester
> a
;
209 tmp
= a
.allocate(1, 0);
214 BOOST_ERROR("Pool allocator cleaned up itself");
216 // Remove memory checker entry (to avoid error later) and
217 // clean up memory leak
219 boost::pool_allocator
<tester
>::deallocate(tmp
, 1);
221 // test allocating zero elements
223 boost::pool_allocator
<tester
> alloc
;
224 tester
* ip
= alloc
.allocate(0);
225 alloc
.deallocate(ip
, 0);
229 void test_mem_usage()
231 typedef boost::pool
<track_alloc
> pool_type
;
234 // Constructor should do nothing; no memory allocation
235 pool_type
pool(sizeof(int));
236 BOOST_TEST(track_alloc::ok());
237 BOOST_TEST(!pool
.release_memory());
238 BOOST_TEST(!pool
.purge_memory());
240 // Should allocate from system
241 pool
.free(pool
.malloc());
242 BOOST_TEST(!track_alloc::ok());
244 // Ask pool to give up memory it's not using; this should succeed
245 BOOST_TEST(pool
.release_memory());
246 BOOST_TEST(track_alloc::ok());
248 // Should allocate from system again
249 pool
.malloc(); // loses the pointer to the returned chunk (*A*)
251 // Ask pool to give up memory it's not using; this should fail
252 BOOST_TEST(!pool
.release_memory());
254 // Force pool to give up memory it's not using; this should succeed
255 // This will clean up the memory leak from (*A*)
256 BOOST_TEST(pool
.purge_memory());
257 BOOST_TEST(track_alloc::ok());
259 // Should allocate from system again
260 pool
.malloc(); // loses the pointer to the returned chunk (*B*)
262 // pool's destructor should purge the memory
263 // This will clean up the memory leak from (*B*)
266 BOOST_TEST(track_alloc::ok());
271 typedef boost::pool_allocator
<void> void_allocator
;
272 typedef boost::fast_pool_allocator
<void> fast_void_allocator
;
274 typedef void_allocator::rebind
<int>::other int_allocator
;
275 typedef fast_void_allocator::rebind
<int>::other fast_int_allocator
;
277 std::vector
<int, int_allocator
> v1
;
278 std::vector
<int, fast_int_allocator
> v2
;
283 std::srand(static_cast<unsigned>(std::time(0)));
290 return boost::report_errors();