1 ////////////////////////////////////////////////////////////////////////////// 2 // 3 // (C) Copyright Ion Gaztanaga 2007-2012. Distributed under the Boost 4 // Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 // See http://www.boost.org/libs/interprocess for documentation. 8 // 9 ////////////////////////////////////////////////////////////////////////////// 10 #include <boost/interprocess/detail/config_begin.hpp> 11 #include <boost/interprocess/managed_shared_memory.hpp> 12 #include <boost/interprocess/smart_ptr/unique_ptr.hpp> 13 #include <boost/interprocess/smart_ptr/deleter.hpp> 14 #include <boost/interprocess/detail/type_traits.hpp> 15 #include <vector> 16 #include <cstddef> 17 #include <string> 18 #include "get_process_id_name.hpp" 19 20 namespace boost { 21 namespace interprocess { 22 namespace test { 23 24 template <class NodePool> 25 struct test_node_pool 26 { 27 static bool allocate_then_deallocate(NodePool &pool); 28 static bool deallocate_free_blocks(NodePool &pool); 29 }; 30 31 template <class NodePool> allocate_then_deallocate(NodePool & pool)32bool test_node_pool<NodePool>::allocate_then_deallocate(NodePool &pool) 33 { 34 const typename NodePool::size_type num_alloc = 1 + 3*pool.get_real_num_node(); 35 36 std::vector<void*> nodes; 37 38 //Precondition, the pool must be empty 39 if(0 != pool.num_free_nodes()){ 40 return false; 41 } 42 43 //First allocate nodes 44 for(std::size_t i = 0; i < num_alloc; ++i){ 45 nodes.push_back(pool.allocate_node()); 46 } 47 48 //Check that the free count is correct 49 if((pool.get_real_num_node() - 1) != pool.num_free_nodes()){ 50 return false; 51 } 52 53 //Now deallocate all and check again 54 for(std::size_t i = 0; i < num_alloc; ++i){ 55 pool.deallocate_node(nodes[i]); 56 } 57 58 //Check that the free count is correct 59 if(4*pool.get_real_num_node() != pool.num_free_nodes()){ 60 return false; 61 } 62 63 pool.deallocate_free_blocks(); 64 65 if(0 != pool.num_free_nodes()){ 66 return false; 67 } 68 69 return true; 70 } 71 72 template <class NodePool> deallocate_free_blocks(NodePool & pool)73bool test_node_pool<NodePool>::deallocate_free_blocks(NodePool &pool) 74 { 75 const std::size_t max_blocks = 10; 76 const std::size_t max_nodes = max_blocks*pool.get_real_num_node(); 77 const std::size_t nodes_per_block = pool.get_real_num_node(); 78 79 std::vector<void*> nodes; 80 81 //Precondition, the pool must be empty 82 if(0 != pool.num_free_nodes()){ 83 return false; 84 } 85 86 //First allocate nodes 87 for(std::size_t i = 0; i < max_nodes; ++i){ 88 nodes.push_back(pool.allocate_node()); 89 } 90 91 //Check that the free count is correct 92 if(0 != pool.num_free_nodes()){ 93 return false; 94 } 95 96 //Now deallocate one of each block per iteration 97 for(std::size_t node_i = 0; node_i < nodes_per_block; ++node_i){ 98 //Deallocate a node per block 99 for(std::size_t i = 0; i < max_blocks; ++i){ 100 pool.deallocate_node(nodes[i*nodes_per_block + node_i]); 101 } 102 103 //Check that the free count is correct 104 if(max_blocks*(node_i+1) != pool.num_free_nodes()){ 105 return false; 106 } 107 108 //Now try to deallocate free blocks 109 pool.deallocate_free_blocks(); 110 111 //Until we don't deallocate the last node of every block 112 //no node should be deallocated 113 if(node_i != (nodes_per_block - 1)){ 114 if(max_blocks*(node_i+1) != pool.num_free_nodes()){ 115 return false; 116 } 117 } 118 else{ 119 //If this is the last iteration, all the memory should 120 //have been deallocated. 121 if(0 != pool.num_free_nodes()){ 122 return false; 123 } 124 } 125 } 126 127 return true; 128 } 129 130 template<class node_pool_t> test_all_node_pool()131bool test_all_node_pool() 132 { 133 using namespace boost::interprocess; 134 typedef managed_shared_memory::segment_manager segment_manager; 135 136 typedef boost::interprocess::test::test_node_pool<node_pool_t> test_node_pool_t; 137 shared_memory_object::remove(test::get_process_id_name()); 138 { 139 managed_shared_memory shm(create_only, test::get_process_id_name(), 4*1024*sizeof(segment_manager::void_pointer)); 140 141 typedef deleter<node_pool_t, segment_manager> deleter_t; 142 typedef unique_ptr<node_pool_t, deleter_t> unique_ptr_t; 143 144 //Delete the pool when the tests end 145 unique_ptr_t p 146 (shm.construct<node_pool_t>(anonymous_instance)(shm.get_segment_manager()) 147 ,deleter_t(shm.get_segment_manager())); 148 149 //Now call each test 150 if(!test_node_pool_t::allocate_then_deallocate(*p)) 151 return false; 152 if(!test_node_pool_t::deallocate_free_blocks(*p)) 153 return false; 154 } 155 shared_memory_object::remove(test::get_process_id_name()); 156 return true; 157 } 158 159 } //namespace test { 160 } //namespace interprocess { 161 } //namespace boost { 162 163 #include <boost/interprocess/detail/config_end.hpp> 164