| ////////////////////////////////////////////////////////////////////////////// |
| // |
| // (C) Copyright Ion Gaztanaga 2007. Distributed under the Boost |
| // Software License, Version 1.0. (See accompanying file |
| // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| // |
| // See http://www.boost.org/libs/interprocess for documentation. |
| // |
| ////////////////////////////////////////////////////////////////////////////// |
| #include <boost/interprocess/detail/config_begin.hpp> |
| #include <boost/interprocess/managed_shared_memory.hpp> |
| #include <boost/interprocess/smart_ptr/unique_ptr.hpp> |
| #include <boost/interprocess/smart_ptr/deleter.hpp> |
| #include <boost/interprocess/detail/type_traits.hpp> |
| #include <vector> |
| #include <cstddef> |
| #include <string> |
| #include "get_process_id_name.hpp" |
| |
| namespace boost { |
| namespace interprocess { |
| namespace test { |
| |
| template <class NodePool> |
| struct test_node_pool |
| { |
| static bool allocate_then_deallocate(NodePool &pool); |
| static bool deallocate_free_blocks(NodePool &pool); |
| }; |
| |
| template <class NodePool> |
| bool test_node_pool<NodePool>::allocate_then_deallocate(NodePool &pool) |
| { |
| const std::size_t num_alloc = 1 + 3*pool.get_real_num_node(); |
| |
| std::vector<void*> nodes; |
| |
| //Precondition, the pool must be empty |
| if(0 != pool.num_free_nodes()){ |
| return false; |
| } |
| |
| //First allocate nodes |
| for(std::size_t i = 0; i < num_alloc; ++i){ |
| nodes.push_back(pool.allocate_node()); |
| } |
| |
| //Check that the free count is correct |
| if((pool.get_real_num_node() - 1) != pool.num_free_nodes()){ |
| return false; |
| } |
| |
| //Now deallocate all and check again |
| for(std::size_t i = 0; i < num_alloc; ++i){ |
| pool.deallocate_node(nodes[i]); |
| } |
| |
| //Check that the free count is correct |
| if(4*pool.get_real_num_node() != pool.num_free_nodes()){ |
| return false; |
| } |
| |
| pool.deallocate_free_blocks(); |
| |
| if(0 != pool.num_free_nodes()){ |
| return false; |
| } |
| |
| return true; |
| } |
| |
| template <class NodePool> |
| bool test_node_pool<NodePool>::deallocate_free_blocks(NodePool &pool) |
| { |
| const std::size_t max_blocks = 10; |
| const std::size_t max_nodes = max_blocks*pool.get_real_num_node(); |
| const std::size_t nodes_per_block = pool.get_real_num_node(); |
| |
| std::vector<void*> nodes; |
| |
| //Precondition, the pool must be empty |
| if(0 != pool.num_free_nodes()){ |
| return false; |
| } |
| |
| //First allocate nodes |
| for(std::size_t i = 0; i < max_nodes; ++i){ |
| nodes.push_back(pool.allocate_node()); |
| } |
| |
| //Check that the free count is correct |
| if(0 != pool.num_free_nodes()){ |
| return false; |
| } |
| |
| //Now deallocate one of each block per iteration |
| for(std::size_t node_i = 0; node_i < nodes_per_block; ++node_i){ |
| //Deallocate a node per block |
| for(std::size_t i = 0; i < max_blocks; ++i){ |
| pool.deallocate_node(nodes[i*nodes_per_block + node_i]); |
| } |
| |
| //Check that the free count is correct |
| if(max_blocks*(node_i+1) != pool.num_free_nodes()){ |
| return false; |
| } |
| |
| //Now try to deallocate free blocks |
| pool.deallocate_free_blocks(); |
| |
| //Until we don't deallocate the last node of every block |
| //no node should be deallocated |
| if(node_i != (nodes_per_block - 1)){ |
| if(max_blocks*(node_i+1) != pool.num_free_nodes()){ |
| return false; |
| } |
| } |
| else{ |
| //If this is the last iteration, all the memory should |
| //have been deallocated. |
| if(0 != pool.num_free_nodes()){ |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| template<class node_pool_t> |
| bool test_all_node_pool() |
| { |
| using namespace boost::interprocess; |
| typedef managed_shared_memory::segment_manager segment_manager; |
| |
| typedef boost::interprocess::test::test_node_pool<node_pool_t> test_node_pool_t; |
| shared_memory_object::remove(test::get_process_id_name()); |
| { |
| managed_shared_memory shm(create_only, test::get_process_id_name(), 4*1024*sizeof(void*)); |
| |
| typedef deleter<node_pool_t, segment_manager> deleter_t; |
| typedef unique_ptr<node_pool_t, deleter_t> unique_ptr_t; |
| |
| //Delete the pool when the tests end |
| unique_ptr_t p |
| (shm.construct<node_pool_t>(anonymous_instance)(shm.get_segment_manager()) |
| ,deleter_t(shm.get_segment_manager())); |
| |
| //Now call each test |
| if(!test_node_pool_t::allocate_then_deallocate(*p)) |
| return false; |
| if(!test_node_pool_t::deallocate_free_blocks(*p)) |
| return false; |
| } |
| shared_memory_object::remove(test::get_process_id_name()); |
| return true; |
| } |
| |
| } //namespace test { |
| } //namespace interprocess { |
| } //namespace boost { |
| |
| #include <boost/interprocess/detail/config_end.hpp> |