1 /* Copyright (C) 2000, 2001 Stephen Cleary 2 * Copyright (C) 2011 Kwan Ting Chan 3 * 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) 7 */ 8 9 #ifndef BOOST_POOL_TEST_SIMP_SEG_STORE_HPP 10 #define BOOST_POOL_TEST_SIMP_SEG_STORE_HPP 11 12 #include <boost/pool/simple_segregated_storage.hpp> 13 #include <boost/assert.hpp> 14 15 #include <boost/detail/lightweight_test.hpp> 16 17 #include <functional> 18 #include <set> 19 #include <utility> 20 #include <vector> 21 22 #include <cstddef> 23 24 class test_simp_seg_store : public boost::simple_segregated_storage<std::size_t> 25 { 26 private: 27 // ::first is the address of the start of the added block, 28 // ::second is the size in bytes of the added block 29 std::vector<std::pair<void*, std::size_t> > allocated_blocks; 30 size_type np_sz; 31 std::set<void*> allocated_chunks; 32 set_partition_size(const size_type sz)33 void set_partition_size(const size_type sz) 34 { 35 if(allocated_blocks.empty()) 36 { 37 np_sz = sz; 38 } 39 else 40 { 41 BOOST_ASSERT(np_sz == sz); 42 } 43 } 44 45 // Return: true if chunk is from added blocks, false otherwise is_inside_allocated_blocks(void * const chunk) const46 bool is_inside_allocated_blocks(void* const chunk) const 47 { 48 typedef std::vector<std::pair<void*, std::size_t> >::const_iterator 49 VPIter; 50 for(VPIter iter = allocated_blocks.begin(); 51 iter != allocated_blocks.end(); 52 ++iter) 53 { 54 if( std::less_equal<void*>()(iter->first, chunk) 55 && std::less_equal<void*>()(static_cast<char*>(chunk) + np_sz, 56 static_cast<char*>(iter->first) + iter->second) ) 57 { 58 return true; 59 } 60 } 61 62 return false; 63 } 64 check_in(void * const chunk)65 void check_in(void* const chunk) 66 { 67 // Check that the newly allocated chunk has not already previously 68 // been allocated, and that the memory does not overlap with 69 // previously allocated chunks 70 for(std::set<void*>::const_iterator iter = allocated_chunks.begin(); 71 iter != allocated_chunks.end(); 72 ++iter) 73 { 74 BOOST_TEST( std::less_equal<void*>()(static_cast<char*>(chunk) 75 + np_sz, *iter) 76 || std::less_equal<void*>()(static_cast<char*>(*iter) 77 + np_sz, chunk) ); 78 } 79 80 allocated_chunks.insert(chunk); 81 } 82 check_out(void * const chunk)83 void check_out(void* const chunk) 84 { 85 BOOST_TEST(allocated_chunks.erase(chunk) == 1); 86 } 87 88 public: test_simp_seg_store()89 test_simp_seg_store() 90 : np_sz(0) {} 91 get_first()92 void* get_first() { return first; } get_nextof(void * const ptr)93 static void*& get_nextof(void* const ptr) { return nextof(ptr); } 94 95 // (Test) Pre: npartition_sz of all added block is the same 96 // different blocks of memory does not overlap add_block(void * const block,const size_type nsz,const size_type npartition_sz)97 void add_block(void* const block, 98 const size_type nsz, const size_type npartition_sz) 99 { 100 set_partition_size(npartition_sz); 101 allocated_blocks.push_back( 102 std::pair<void*, std::size_t>(block, nsz) ); 103 boost::simple_segregated_storage<std::size_t>::add_block( 104 block, nsz, npartition_sz ); 105 // Post: !empty() 106 BOOST_TEST(!empty()); 107 } 108 109 // (Test) Pre: npartition_sz of all added block is the same 110 // different blocks of memory does not overlap add_ordered_block(void * const block,const size_type nsz,const size_type npartition_sz)111 void add_ordered_block(void* const block, 112 const size_type nsz, const size_type npartition_sz) 113 { 114 set_partition_size(npartition_sz); 115 allocated_blocks.push_back( 116 std::pair<void*, std::size_t>(block, nsz) ); 117 boost::simple_segregated_storage<std::size_t>::add_ordered_block( 118 block, nsz, npartition_sz ); 119 // Post: !empty() 120 BOOST_TEST(!empty()); 121 } 122 malloc()123 void* malloc() 124 { 125 void* const ret 126 = boost::simple_segregated_storage<std::size_t>::malloc(); 127 // Chunk returned should actually be from added blocks 128 BOOST_TEST(is_inside_allocated_blocks(ret)); 129 check_in(ret); 130 return ret; 131 } 132 free(void * const chunk)133 void free(void* const chunk) 134 { 135 BOOST_ASSERT(chunk); 136 check_out(chunk); 137 boost::simple_segregated_storage<std::size_t>::free(chunk); 138 // Post: !empty() 139 BOOST_TEST(!empty()); 140 } 141 ordered_free(void * const chunk)142 void ordered_free(void* const chunk) 143 { 144 BOOST_ASSERT(chunk); 145 check_out(chunk); 146 boost::simple_segregated_storage<std::size_t>::ordered_free(chunk); 147 // Post: !empty() 148 BOOST_TEST(!empty()); 149 } 150 malloc_n(size_type n,size_type partition_size)151 void* malloc_n(size_type n, size_type partition_size) 152 { 153 void* const ret 154 = boost::simple_segregated_storage<std::size_t>::malloc_n( 155 n, partition_size ); 156 157 if(ret) 158 { 159 for(std::size_t i=0; i < n; ++i) 160 { 161 void* const chunk = static_cast<char*>(ret) 162 + (i * partition_size); 163 // Memory returned should actually be from added blocks 164 BOOST_TEST(is_inside_allocated_blocks(chunk)); 165 check_in(chunk); 166 } 167 } 168 169 return ret; 170 } 171 }; 172 173 #endif // BOOST_POOL_TEST_SIMP_SEG_STORE_HPP 174