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> |
32 | bool 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> |
73 | bool 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> |
131 | bool 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(filename: 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(filename: 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 |