ad1b7f301c
- Removed all tabs - Changed all Doxygen @cond/@endcond tags with preprocessor sections, as Doxygen still has some problems when parsing this code. This also makes unmatched Doxygen sections a compilation error, which is easier to detect.
164 lines
4.6 KiB
C++
164 lines
4.6 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// (C) Copyright Ion Gaztanaga 2007-2012. 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 typename NodePool::size_type 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(segment_manager::void_pointer));
|
|
|
|
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>
|