]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/interprocess/test/segment_manager_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / interprocess / test / segment_manager_test.cpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2004-2019. 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
11 #include <boost/interprocess/indexes/flat_map_index.hpp>
12 #include <boost/interprocess/indexes/map_index.hpp>
13 #include <boost/interprocess/indexes/null_index.hpp>
14 #include <boost/interprocess/indexes/unordered_map_index.hpp>
15 #include <boost/interprocess/indexes/iset_index.hpp>
16 #include <boost/interprocess/indexes/iunordered_set_index.hpp>
17
18 #include <boost/interprocess/mem_algo/simple_seq_fit.hpp>
19 #include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
20 #include <boost/interprocess/mapped_region.hpp>
21 #include <boost/interprocess/segment_manager.hpp>
22 #include <boost/interprocess/shared_memory_object.hpp>
23 #include <boost/interprocess/sync/mutex_family.hpp>
24 #include <boost/interprocess/exceptions.hpp>
25 #include "get_process_id_name.hpp"
26 #include <cstddef>
27 #include <new>
28 #include <cstring>
29
30 using namespace boost::interprocess;
31
32 template <class SegmentManager>
33 struct atomic_func_test
34 {
35 SegmentManager &rsm;
36 int *object;
37
38 atomic_func_test(SegmentManager &sm)
39 : rsm(sm), object()
40 {}
41
42 void operator()()
43 {
44 object = rsm.template find<int>("atomic_func_find_object").first;
45 }
46 private:
47 atomic_func_test operator=(const atomic_func_test&);
48 atomic_func_test(const atomic_func_test&);
49 };
50
51 template <class SegmentManager>
52 bool test_segment_manager()
53 {
54 typedef typename SegmentManager::size_type size_type;
55 const unsigned int ShmSizeSize = 1024*64u;
56 std::string shmname(test::get_process_id_name());
57
58 shared_memory_object::remove(shmname.c_str());
59 shared_memory_object sh_mem( create_only, shmname.c_str(), read_write );
60 sh_mem.truncate( ShmSizeSize );
61 mapped_region mapping( sh_mem, read_write );
62
63 SegmentManager* seg_mgr = new( mapping.get_address() ) SegmentManager( ShmSizeSize );
64 std::size_t free_mem_before = seg_mgr->get_free_memory();
65 std::size_t size_before = seg_mgr->get_size();
66
67 if(size_before != ShmSizeSize)
68 return false;
69 if(!seg_mgr->all_memory_deallocated())
70 return false;
71 if(seg_mgr->get_min_size() >= ShmSizeSize)
72 return false;
73
74 {//test get_free_memory() / allocate()/deallocate()
75 const size_type Size = ShmSizeSize/2;
76 void *mem = seg_mgr->allocate(Size+1);
77 const size_type free_mem = seg_mgr->get_free_memory();
78 if(free_mem >= Size)
79 return false;
80 if(seg_mgr->all_memory_deallocated())
81 return false;
82 const size_type Size2 = free_mem/2;
83 void *mem2 = seg_mgr->allocate(size_type(Size2+1), std::nothrow);
84 if(seg_mgr->get_free_memory() >= Size2)
85 return false;
86 if(seg_mgr->size(mem) < (Size+1))
87 return false;
88 if(seg_mgr->size(mem2) < (Size2+1))
89 return false;
90 seg_mgr->deallocate(mem);
91 seg_mgr->deallocate(mem2);
92 if(!seg_mgr->all_memory_deallocated())
93 return false;
94 if(seg_mgr->get_free_memory() != free_mem_before)
95 return false;
96 BOOST_TRY{ seg_mgr->allocate(ShmSizeSize*2); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
97 if(seg_mgr->get_free_memory() != free_mem_before)
98 return false;
99 if(seg_mgr->allocate(ShmSizeSize*2, std::nothrow))
100 return false;
101 if(seg_mgr->get_free_memory() != free_mem_before)
102 return false;
103 }
104 {//test allocate_aligned
105 const std::size_t Alignment = 128u;
106 void *mem = seg_mgr->allocate_aligned(ShmSizeSize/4, Alignment);
107 if(seg_mgr->all_memory_deallocated())
108 return false;
109 std::size_t offset = static_cast<std::size_t>
110 (static_cast<const char *>(mem) - static_cast<const char *>(mapping.get_address()));
111 if(offset & (Alignment-1))
112 return false;
113 void *mem2 = seg_mgr->allocate_aligned(ShmSizeSize/4, Alignment, std::nothrow);
114 std::size_t offset2 = static_cast<std::size_t>
115 (static_cast<const char *>(mem2) - static_cast<const char *>(mapping.get_address()));
116 if(offset2 & (Alignment-1))
117 return false;
118 seg_mgr->deallocate(mem);
119 seg_mgr->deallocate(mem2);
120 if(!seg_mgr->all_memory_deallocated())
121 return false;
122 if(seg_mgr->get_free_memory() != free_mem_before)
123 return false;
124 BOOST_TRY{ seg_mgr->allocate_aligned(ShmSizeSize*2, Alignment); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
125 if(seg_mgr->get_free_memory() != free_mem_before)
126 return false;
127 if(seg_mgr->allocate_aligned(ShmSizeSize*2, Alignment, std::nothrow))
128 return false;
129 if(seg_mgr->get_free_memory() != free_mem_before)
130 return false;
131 }
132 {//test shrink_to_fit
133
134 seg_mgr->shrink_to_fit();
135 if(!seg_mgr->all_memory_deallocated())
136 return false;
137 std::size_t empty_shrunk_size = seg_mgr->get_size();
138 std::size_t empty_shrunk_free_mem = seg_mgr->get_free_memory();
139 if(empty_shrunk_size >= size_before)
140 return false;
141 if(empty_shrunk_free_mem >= size_before)
142 return false;
143 seg_mgr->grow(size_type(size_before - empty_shrunk_size));
144 if(seg_mgr->get_size() != size_before)
145 return false;
146 if(seg_mgr->get_free_memory() != free_mem_before)
147 return false;
148 if(!seg_mgr->all_memory_deallocated())
149 return false;
150 }
151 {//test zero_free_memory
152 const size_type Size(ShmSizeSize/2+1), Size2(ShmSizeSize/8);
153 void *mem = seg_mgr->allocate(Size);
154 void *mem2 = seg_mgr->allocate(Size2);
155 //Mark memory to non-zero
156 std::memset(mem, 0xFF, Size);
157 std::memset(mem2, 0xFF, Size2);
158 //Deallocate and check still non-zero
159 seg_mgr->deallocate(mem);
160 seg_mgr->deallocate(mem2);
161 { //Use byte per byte comparison as "static unsigned char zerobuf[Size]"
162 //seems to be problematic in some compilers
163 unsigned char *const mem_uch_ptr = static_cast<unsigned char *>(mem);
164 unsigned char *const mem2_uch_ptr = static_cast<unsigned char *>(mem2);
165 size_type zeroes = 0;
166 for(size_type i = 0; i != Size; ++i){
167 if(!mem_uch_ptr[i])
168 ++zeroes;
169 }
170 if(zeroes == Size)
171 return false;
172
173 zeroes = 0;
174 for(size_type i = 0; i != Size2; ++i){
175 if(!mem2_uch_ptr[i])
176 ++zeroes;
177 }
178 if(zeroes == Size2)
179 return false;
180 }
181 //zero_free_memory and check it's zeroed
182 seg_mgr->zero_free_memory();
183 //TODO: some parts are not zeroed because they are used
184 //as internal metadata, find a way to test this
185 //if(std::memcmp(mem, zerobuf, Size))
186 //return false;
187 //if(std::memcmp(mem2, zerobuf, Size2))
188 //return false;
189 if(seg_mgr->get_free_memory() != free_mem_before)
190 return false;
191 if(!seg_mgr->all_memory_deallocated())
192 return false;
193 }
194
195 {//test anonymous object
196 int *int_object = seg_mgr->template construct<int>(anonymous_instance)();
197 if(1 != seg_mgr->get_instance_length(int_object))
198 return false;
199 if(anonymous_type != seg_mgr->get_instance_type(int_object))
200 return false;
201 if(seg_mgr->get_instance_name(int_object))
202 return false;
203 seg_mgr->destroy_ptr(int_object);
204 int const int_array_values[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
205 int *int_array = seg_mgr->template construct_it<int>(anonymous_instance, std::nothrow)[10](&int_array_values[0]);
206 if(10 != seg_mgr->get_instance_length(int_object))
207 return false;
208 if(anonymous_type != seg_mgr->get_instance_type(int_array))
209 return false;
210 if(seg_mgr->get_instance_name(int_array))
211 return false;
212 seg_mgr->destroy_ptr(int_array);
213 BOOST_TRY{ seg_mgr->template construct<int>(anonymous_instance)[ShmSizeSize](); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
214 if(seg_mgr->template construct<int>(anonymous_instance, std::nothrow)[ShmSizeSize]())
215 BOOST_TRY{ seg_mgr->template construct_it<long int>(anonymous_instance)[ShmSizeSize](&int_array_values[0]); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
216 if(seg_mgr->template construct_it<int>(anonymous_instance, std::nothrow)[ShmSizeSize](&int_array_values[0]))
217 return false;
218 if(seg_mgr->get_free_memory() != free_mem_before)
219 return false;
220 if(!seg_mgr->all_memory_deallocated())
221 return false;
222 }
223
224 {//test named object
225 const char *const object1_name = "object1";
226 const char *const object2_name = "object2";
227 int const int_array_values[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
228
229 for(std::size_t i = 0; i != 1/*4*/; ++i){
230 if(seg_mgr->template find<unsigned int>(object1_name).first)
231 return false;
232 //Single element construction
233 unsigned int *uint_object = 0;
234 switch(i){
235 case 0:
236 uint_object = seg_mgr->template construct<unsigned int>(object1_name)();
237 break;
238 case 1:
239 uint_object = seg_mgr->template construct<unsigned int>(object1_name, std::nothrow)();
240 break;
241 case 2:
242 uint_object = seg_mgr->template find_or_construct<unsigned int>(object1_name)();
243 break;
244 case 3:
245 uint_object = seg_mgr->template find_or_construct<unsigned int>(object1_name, std::nothrow)();
246 break;
247 }
248 std::pair<unsigned int*, std::size_t> find_ret = seg_mgr->template find<unsigned int>(object1_name);
249 if(uint_object != find_ret.first)
250 return false;
251 if(1 != find_ret.second)
252 return false;
253 if(1 != seg_mgr->get_instance_length(uint_object))
254 return false;
255 if(named_type != seg_mgr->get_instance_type(uint_object))
256 return false;
257 if(std::strcmp(object1_name, seg_mgr->get_instance_name(uint_object)))
258 return false;
259 //Array construction
260 if(seg_mgr->template find<int>(object2_name).first)
261 return false;
262 int *int_array = 0;
263 switch(i){
264 case 0:
265 int_array = seg_mgr->template construct_it<int>(object2_name)[10](&int_array_values[0]);
266 break;
267 case 1:
268 int_array = seg_mgr->template construct_it<int>(object2_name, std::nothrow)[10](&int_array_values[0]);
269 break;
270 case 2:
271 int_array = seg_mgr->template find_or_construct_it<int>(object2_name)[10](&int_array_values[0]);
272 break;
273 case 3:
274 int_array = seg_mgr->template find_or_construct_it<int>(object2_name, std::nothrow)[10](&int_array_values[0]);
275 break;
276 }
277 std::pair<int*, std::size_t> find_ret2 = seg_mgr->template find<int>(object2_name);
278 if(int_array != find_ret2.first)
279 return false;
280 if(10 != find_ret2.second)
281 return false;
282 if(10 != seg_mgr->get_instance_length(int_array))
283 return false;
284 if(named_type != seg_mgr->get_instance_type(int_array))
285 return false;
286 if(std::strcmp(object2_name, seg_mgr->get_instance_name(int_array)))
287 return false;
288 if(seg_mgr->get_num_named_objects() != 2)
289 return false;
290 typename SegmentManager::const_named_iterator nb(seg_mgr->named_begin());
291 typename SegmentManager::const_named_iterator ne(seg_mgr->named_end());
292 for(std::size_t j = 0, imax = seg_mgr->get_num_named_objects(); j != imax; ++j){ ++nb; }
293 if(nb != ne)
294 return false;
295 seg_mgr->destroy_ptr(uint_object);
296 seg_mgr->template destroy<int>(object2_name);
297 }
298 BOOST_TRY{ seg_mgr->template construct<unsigned int>(object1_name)[ShmSizeSize](); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
299 if(seg_mgr->template construct<int>(object2_name, std::nothrow)[ShmSizeSize]())
300 BOOST_TRY{ seg_mgr->template construct_it<int>(object1_name)[ShmSizeSize](&int_array_values[0]); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
301 if(seg_mgr->template construct_it<int>(object2_name, std::nothrow)[ShmSizeSize](&int_array_values[0]))
302 return false;
303 seg_mgr->shrink_to_fit_indexes();
304 if(seg_mgr->get_free_memory() != free_mem_before)
305 return false;
306 if(!seg_mgr->all_memory_deallocated())
307 return false;
308 seg_mgr->reserve_named_objects(1);
309 //In indexes with no capacity() memory won't be allocated so don't check anything was allocated.
310 //if(seg_mgr->all_memory_deallocated()) return false;
311 seg_mgr->shrink_to_fit_indexes();
312 if(!seg_mgr->all_memory_deallocated())
313 return false;
314 }
315
316 {//test unique object
317 int const int_array_values[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
318
319 for(std::size_t i = 0; i != 4; ++i){
320 if(seg_mgr->template find<unsigned int>(unique_instance).first)
321 return false;
322 //Single element construction
323 unsigned int *uint_object = 0;
324 switch(i){
325 case 0:
326 uint_object = seg_mgr->template construct<unsigned int>(unique_instance)();
327 break;
328 case 1:
329 uint_object = seg_mgr->template construct<unsigned int>(unique_instance, std::nothrow)();
330 break;
331 case 2:
332 uint_object = seg_mgr->template find_or_construct<unsigned int>(unique_instance)();
333 break;
334 case 3:
335 uint_object = seg_mgr->template find_or_construct<unsigned int>(unique_instance, std::nothrow)();
336 break;
337 }
338 std::pair<unsigned int*, std::size_t> find_ret = seg_mgr->template find<unsigned int>(unique_instance);
339 if(uint_object != find_ret.first)
340 return false;
341 if(1 != find_ret.second)
342 return false;
343 if(1 != seg_mgr->get_instance_length(uint_object))
344 return false;
345 if(unique_type != seg_mgr->get_instance_type(uint_object))
346 return false;
347 if(std::strcmp(typeid(unsigned int).name(), seg_mgr->get_instance_name(uint_object)))
348 return false;
349 //Array construction
350 if(seg_mgr->template find<int>(unique_instance).first)
351 return false;
352 int *int_array = 0;
353 switch(i){
354 case 0:
355 int_array = seg_mgr->template construct_it<int>(unique_instance)[10](&int_array_values[0]);
356 break;
357 case 1:
358 int_array = seg_mgr->template construct_it<int>(unique_instance, std::nothrow)[10](&int_array_values[0]);
359 break;
360 case 2:
361 int_array = seg_mgr->template find_or_construct_it<int>(unique_instance)[10](&int_array_values[0]);
362 break;
363 case 3:
364 int_array = seg_mgr->template find_or_construct_it<int>(unique_instance, std::nothrow)[10](&int_array_values[0]);
365 break;
366 }
367 std::pair<int*, std::size_t> find_ret2 = seg_mgr->template find<int>(unique_instance);
368 if(int_array != find_ret2.first)
369 return false;
370 if(10 != find_ret2.second)
371 return false;
372 if(10 != seg_mgr->get_instance_length(int_array))
373 return false;
374 if(unique_type != seg_mgr->get_instance_type(int_array))
375 return false;
376 if(std::strcmp(typeid(int).name(), seg_mgr->get_instance_name(int_array)))
377 return false;
378 if(seg_mgr->get_num_unique_objects() != 2)
379 return false;
380 typename SegmentManager::const_unique_iterator nb(seg_mgr->unique_begin());
381 typename SegmentManager::const_unique_iterator ne(seg_mgr->unique_end());
382 for(std::size_t j = 0, imax = seg_mgr->get_num_unique_objects(); j != imax; ++j){ ++nb; }
383 if(nb != ne)
384 return false;
385 seg_mgr->destroy_ptr(uint_object);
386 seg_mgr->template destroy<int>(unique_instance);
387 }
388 BOOST_TRY{ seg_mgr->template construct<unsigned int>(unique_instance)[ShmSizeSize](); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
389 if(seg_mgr->template construct<int>(unique_instance, std::nothrow)[ShmSizeSize]())
390 BOOST_TRY{ seg_mgr->template construct_it<long int>(unique_instance)[ShmSizeSize](&int_array_values[0]); }BOOST_CATCH(interprocess_exception&){} BOOST_CATCH_END
391 if(seg_mgr->template construct_it<int>(unique_instance, std::nothrow)[ShmSizeSize](&int_array_values[0]))
392 return false;
393 seg_mgr->shrink_to_fit_indexes();
394 if(seg_mgr->get_free_memory() != free_mem_before)
395 return false;
396 if(!seg_mgr->all_memory_deallocated())
397 return false;
398 seg_mgr->reserve_unique_objects(1);
399 //In indexes with no capacity() memory won't be allocated so don't check anything was allocated.
400 //if(seg_mgr->all_memory_deallocated()) return false;
401 seg_mgr->shrink_to_fit_indexes();
402 if(!seg_mgr->all_memory_deallocated())
403 return false;
404 }
405 {//test allocator/deleter
406 if(!seg_mgr->all_memory_deallocated())
407 return false;
408 typedef typename SegmentManager::template allocator<float>::type allocator_t;
409
410 allocator_t alloc(seg_mgr->template get_allocator<float>());
411
412 if(!seg_mgr->all_memory_deallocated())
413 return false;
414 offset_ptr<float> f = alloc.allocate(50);
415 if(seg_mgr->all_memory_deallocated())
416 return false;
417 alloc.deallocate(f, 50);
418 if(!seg_mgr->all_memory_deallocated())
419 return false;
420 typedef typename SegmentManager::template deleter<float>::type deleter_t;
421 deleter_t delet(seg_mgr->template get_deleter<float>());
422 delet(seg_mgr->template construct<float>(anonymous_instance)());
423 if(!seg_mgr->all_memory_deallocated())
424 return false;
425 }
426 {//test allocator/deleter
427 if(!seg_mgr->all_memory_deallocated())
428 return false;
429 int *int_object = seg_mgr->template construct<int>("atomic_func_find_object")();
430 atomic_func_test<SegmentManager> func(*seg_mgr);
431 seg_mgr->atomic_func(func);
432 if(int_object != func.object)
433 return 1;
434 seg_mgr->destroy_ptr(int_object);
435 seg_mgr->shrink_to_fit_indexes();
436 if(!seg_mgr->all_memory_deallocated())
437 return false;
438 }
439 {//test get_memory_algorithm
440 {
441 typename SegmentManager::memory_algorithm & mem_algo =
442 seg_mgr->get_memory_algorithm();
443 boost::ignore_unused(mem_algo);
444 }
445 {
446 const typename SegmentManager::memory_algorithm & mem_algo =
447 const_cast<const SegmentManager*>(seg_mgr)->get_memory_algorithm();
448 boost::ignore_unused(mem_algo);
449 }
450 }
451 return true;
452 }
453
454 template<class MemoryAlgorithm>
455 bool test_each_algo()
456 {
457 {
458 typedef segment_manager< char, MemoryAlgorithm, flat_map_index > segment_manager_t;
459 if(!test_segment_manager<segment_manager_t>())
460 return false;
461 }
462 {
463 typedef segment_manager< char, MemoryAlgorithm, map_index > segment_manager_t;
464 if(!test_segment_manager<segment_manager_t>())
465 return false;
466 }
467 /*
468 {
469 typedef segment_manager< char, MemoryAlgorithm, null_index > segment_manager_t;
470 if(!test_segment_manager<segment_manager_t>())
471 return false;
472 }*/
473 /*
474 {
475 typedef segment_manager< char, MemoryAlgorithm, unordered_map_index > segment_manager_t;
476 if(!test_segment_manager<segment_manager_t>())
477 return false;
478 }*/
479 {
480 typedef segment_manager< char, MemoryAlgorithm, iset_index > segment_manager_t;
481 if(!test_segment_manager<segment_manager_t>())
482 return false;
483 }
484 {
485 typedef segment_manager< char, MemoryAlgorithm, iunordered_set_index > segment_manager_t;
486 if(!test_segment_manager<segment_manager_t>())
487 return false;
488 }
489 return true;
490 }
491
492 int main()
493 {
494 if(!test_each_algo< simple_seq_fit< null_mutex_family > >())
495 return 1;
496 if(!test_each_algo< rbtree_best_fit< null_mutex_family > >())
497 return 1;
498
499 return 0;
500 }