summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/pool/test/test_pool_alloc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/pool/test/test_pool_alloc.cpp')
-rw-r--r--src/boost/libs/pool/test/test_pool_alloc.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/boost/libs/pool/test/test_pool_alloc.cpp b/src/boost/libs/pool/test/test_pool_alloc.cpp
new file mode 100644
index 00000000..b0b50eab
--- /dev/null
+++ b/src/boost/libs/pool/test/test_pool_alloc.cpp
@@ -0,0 +1,291 @@
+/* Copyright (C) 2000, 2001 Stephen Cleary
+ * Copyright (C) 2011 Kwan Ting Chan
+ *
+ * Use, modification and distribution is subject to the
+ * Boost Software License, Version 1.0. (See accompanying
+ * file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#include "random_shuffle.hpp"
+#include <boost/pool/pool_alloc.hpp>
+#include <boost/pool/object_pool.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <algorithm>
+#include <deque>
+#include <list>
+#include <set>
+#include <stdexcept>
+#include <vector>
+
+#include <cstdlib>
+#include <ctime>
+
+// Each "tester" object below checks into and out of the "cdtor_checker",
+// which will check for any problems related to the construction/destruction of
+// "tester" objects.
+class cdtor_checker
+{
+private:
+ // Each constructed object registers its "this" pointer into "objs"
+ std::set<void*> objs;
+
+public:
+ // True iff all objects that have checked in have checked out
+ bool ok() const { return objs.empty(); }
+
+ ~cdtor_checker()
+ {
+ BOOST_TEST(ok());
+ }
+
+ void check_in(void * const This)
+ {
+ BOOST_TEST(objs.find(This) == objs.end());
+ objs.insert(This);
+ }
+
+ void check_out(void * const This)
+ {
+ BOOST_TEST(objs.find(This) != objs.end());
+ objs.erase(This);
+ }
+};
+static cdtor_checker mem;
+
+struct tester
+{
+ tester(bool throw_except = false)
+ {
+ if(throw_except)
+ {
+ throw std::logic_error("Deliberate constructor exception");
+ }
+
+ mem.check_in(this);
+ }
+
+ tester(const tester &)
+ {
+ mem.check_in(this);
+ }
+
+ ~tester()
+ {
+ mem.check_out(this);
+ }
+};
+
+// This is a wrapper around a UserAllocator. It just registers alloc/dealloc
+// to/from the system memory. It's used to make sure pool's are allocating
+// and deallocating system memory properly.
+// Do NOT use this class with static or singleton pools.
+template <typename UserAllocator>
+struct TrackAlloc
+{
+ typedef typename UserAllocator::size_type size_type;
+ typedef typename UserAllocator::difference_type difference_type;
+
+ static std::set<char *> allocated_blocks;
+
+ static char * malloc(const size_type bytes)
+ {
+ char * const ret = UserAllocator::malloc(bytes);
+ allocated_blocks.insert(ret);
+ return ret;
+ }
+
+ static void free(char * const block)
+ {
+ BOOST_TEST(allocated_blocks.find(block) != allocated_blocks.end());
+ allocated_blocks.erase(block);
+ UserAllocator::free(block);
+ }
+
+ static bool ok()
+ {
+ return allocated_blocks.empty();
+ }
+};
+template <typename UserAllocator>
+std::set<char *> TrackAlloc<UserAllocator>::allocated_blocks;
+
+typedef TrackAlloc<boost::default_user_allocator_new_delete> track_alloc;
+
+void test()
+{
+ {
+ // Do nothing pool
+ boost::object_pool<tester> pool;
+ }
+
+ {
+ // Construct several tester objects. Don't delete them (i.e.,
+ // test pool's garbage collection).
+ boost::object_pool<tester> pool;
+ for(int i=0; i < 10; ++i)
+ {
+ pool.construct();
+ }
+ }
+
+ {
+ // Construct several tester objects. Delete some of them.
+ boost::object_pool<tester> pool;
+ std::vector<tester *> v;
+ for(int i=0; i < 10; ++i)
+ {
+ v.push_back(pool.construct());
+ }
+ pool_test_random_shuffle(v.begin(), v.end());
+ for(int j=0; j < 5; ++j)
+ {
+ pool.destroy(v[j]);
+ }
+ }
+
+ {
+ // Test how pool reacts with constructors that throw exceptions.
+ // Shouldn't have any memory leaks.
+ boost::object_pool<tester> pool;
+ for(int i=0; i < 5; ++i)
+ {
+ pool.construct();
+ }
+ for(int j=0; j < 5; ++j)
+ {
+ try
+ {
+ // The following constructions will raise an exception.
+ pool.construct(true);
+ }
+ catch(const std::logic_error &) {}
+ }
+ }
+}
+
+void test_alloc()
+{
+ {
+ // Allocate several tester objects. Delete one.
+ std::vector<tester, boost::pool_allocator<tester> > l;
+ for(int i=0; i < 10; ++i)
+ {
+ l.push_back(tester());
+ }
+ l.pop_back();
+ }
+
+ {
+ // Allocate several tester objects. Delete two.
+ std::deque<tester, boost::pool_allocator<tester> > l;
+ for(int i=0; i < 10; ++i)
+ {
+ l.push_back(tester());
+ }
+ l.pop_back();
+ l.pop_front();
+ }
+
+ {
+ // Allocate several tester objects. Delete two.
+ std::list<tester, boost::fast_pool_allocator<tester> > l;
+ // lists rebind their allocators, so dumping is useless
+ for(int i=0; i < 10; ++i)
+ {
+ l.push_back(tester());
+ }
+ l.pop_back();
+ l.pop_front();
+ }
+
+ tester * tmp;
+ {
+ // Create a memory leak on purpose. (Allocator doesn't have
+ // garbage collection)
+ // (Note: memory leak)
+ boost::pool_allocator<tester> a;
+ tmp = a.allocate(1, 0);
+ new (tmp) tester();
+ }
+ if(mem.ok())
+ {
+ BOOST_ERROR("Pool allocator cleaned up itself");
+ }
+ // Remove memory checker entry (to avoid error later) and
+ // clean up memory leak
+ tmp->~tester();
+ boost::pool_allocator<tester>::deallocate(tmp, 1);
+
+ // test allocating zero elements
+ {
+ boost::pool_allocator<tester> alloc;
+ tester* ip = alloc.allocate(0);
+ alloc.deallocate(ip, 0);
+ }
+}
+
+void test_mem_usage()
+{
+ typedef boost::pool<track_alloc> pool_type;
+
+ {
+ // Constructor should do nothing; no memory allocation
+ pool_type pool(sizeof(int));
+ BOOST_TEST(track_alloc::ok());
+ BOOST_TEST(!pool.release_memory());
+ BOOST_TEST(!pool.purge_memory());
+
+ // Should allocate from system
+ pool.free(pool.malloc());
+ BOOST_TEST(!track_alloc::ok());
+
+ // Ask pool to give up memory it's not using; this should succeed
+ BOOST_TEST(pool.release_memory());
+ BOOST_TEST(track_alloc::ok());
+
+ // Should allocate from system again
+ pool.malloc(); // loses the pointer to the returned chunk (*A*)
+
+ // Ask pool to give up memory it's not using; this should fail
+ BOOST_TEST(!pool.release_memory());
+
+ // Force pool to give up memory it's not using; this should succeed
+ // This will clean up the memory leak from (*A*)
+ BOOST_TEST(pool.purge_memory());
+ BOOST_TEST(track_alloc::ok());
+
+ // Should allocate from system again
+ pool.malloc(); // loses the pointer to the returned chunk (*B*)
+
+ // pool's destructor should purge the memory
+ // This will clean up the memory leak from (*B*)
+ }
+
+ BOOST_TEST(track_alloc::ok());
+}
+
+void test_void()
+{
+ typedef boost::pool_allocator<void> void_allocator;
+ typedef boost::fast_pool_allocator<void> fast_void_allocator;
+
+ typedef void_allocator::rebind<int>::other int_allocator;
+ typedef fast_void_allocator::rebind<int>::other fast_int_allocator;
+
+ std::vector<int, int_allocator> v1;
+ std::vector<int, fast_int_allocator> v2;
+}
+
+int main()
+{
+ std::srand(static_cast<unsigned>(std::time(0)));
+
+ test();
+ test_alloc();
+ test_mem_usage();
+ test_void();
+
+ return boost::report_errors();
+}