1 ////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2006-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
11 #ifndef BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER
12 #define BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER
13
14 #include <boost/interprocess/detail/config_begin.hpp>
15 #include "check_equal_containers.hpp"
16 #include <map>
17
18 // interprocess
19 #include <boost/interprocess/containers/pair.hpp>
20 // interprocess/detail
21 #include <boost/interprocess/detail/utilities.hpp>
22 // intrusive/detail
23 #include <boost/intrusive/detail/minimal_pair_header.hpp>
24 #include <boost/intrusive/detail/minimal_less_equal_header.hpp>
25 // std
26 #include <string>
27
28 #include "print_container.hpp"
29 #include "get_process_id_name.hpp"
30
31 template<class T1, class T2, class T3, class T4>
operator ==(std::pair<T1,T2> & p1,std::pair<T1,T2> & p2)32 bool operator ==(std::pair<T1, T2> &p1, std::pair<T1, T2> &p2)
33 {
34 return p1.first == p2.first && p1.second == p2.second;
35 }
36
37 namespace boost{
38 namespace interprocess{
39 namespace test{
40
41 template<class ManagedSharedMemory
42 ,class MyShmMap
43 ,class MyStdMap
44 ,class MyShmMultiMap
45 ,class MyStdMultiMap>
map_test()46 int map_test ()
47 {
48 typedef typename MyShmMap::key_type IntType;
49 typedef boost::interprocess::pair<IntType, IntType> IntPairType;
50 typedef typename MyStdMap::value_type StdPairType;
51 const int memsize = 65536;
52 const char *const shMemName = test::get_process_id_name();
53 const int max = 100;
54
55 try{
56 //Create shared memory
57 shared_memory_object::remove(shMemName);
58 ManagedSharedMemory segment(create_only, shMemName, memsize);
59
60 segment.reserve_named_objects(100);
61
62 //Shared memory allocator must be always be initialized
63 //since it has no default constructor
64 MyShmMap *shmmap =
65 segment.template construct<MyShmMap>("MyShmMap")
66 (std::less<IntType>(), segment.get_segment_manager());
67
68 MyStdMap *stdmap = new MyStdMap;
69
70 MyShmMultiMap *shmmultimap =
71 segment.template construct<MyShmMultiMap>("MyShmMultiMap")
72 (std::less<IntType>(), segment.get_segment_manager());
73
74 MyStdMultiMap *stdmultimap = new MyStdMultiMap;
75
76 //Test construction from a range
77 {
78 //This is really nasty, but we have no other simple choice
79 IntPairType aux_vect[50];
80 for(int i = 0; i < 50; ++i){
81 IntType i1(i/2);
82 IntType i2(i/2);
83 new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
84 }
85
86 typedef typename MyStdMap::value_type StdValueType;
87 typedef typename MyStdMap::key_type StdKeyType;
88 typedef typename MyStdMap::mapped_type StdMappedType;
89 StdValueType aux_vect2[50];
90 for(int i = 0; i < 50; ++i){
91 new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
92 }
93
94 IntPairType aux_vect3[50];
95 for(int i = 0; i < 50; ++i){
96 IntType i1(i/2);
97 IntType i2(i/2);
98 new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
99 }
100
101 MyShmMap *shmmap2 =
102 segment.template construct<MyShmMap>("MyShmMap2")
103 ( ::boost::make_move_iterator(&aux_vect[0])
104 , ::boost::make_move_iterator(aux_vect + 50)
105 , std::less<IntType>(), segment.get_segment_manager());
106
107 MyStdMap *stdmap2 = new MyStdMap(aux_vect2, aux_vect2 + 50);
108
109 MyShmMultiMap *shmmultimap2 =
110 segment.template construct<MyShmMultiMap>("MyShmMultiMap2")
111 ( ::boost::make_move_iterator(&aux_vect3[0])
112 , ::boost::make_move_iterator(aux_vect3 + 50)
113 , std::less<IntType>(), segment.get_segment_manager());
114
115 MyStdMultiMap *stdmultimap2 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50);
116 if(!CheckEqualContainers(shmmap2, stdmap2)) return 1;
117 if(!CheckEqualContainers(shmmultimap2, stdmultimap2)) return 1;
118
119 //ordered range insertion
120 //This is really nasty, but we have no other simple choice
121 for(int i = 0; i < 50; ++i){
122 IntType i1(i);
123 IntType i2(i);
124 new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
125 }
126
127 for(int i = 0; i < 50; ++i){
128 new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i));
129 }
130
131 for(int i = 0; i < 50; ++i){
132 IntType i1(i);
133 IntType i2(i);
134 new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
135 }
136
137 MyShmMap *shmmap3 =
138 segment.template construct<MyShmMap>("MyShmMap3")
139 ( ordered_unique_range
140 , ::boost::make_move_iterator(&aux_vect[0])
141 , ::boost::make_move_iterator(aux_vect + 50)
142 , std::less<IntType>(), segment.get_segment_manager());
143
144 MyStdMap *stdmap3 = new MyStdMap(aux_vect2, aux_vect2 + 50);
145
146 MyShmMultiMap *shmmultimap3 =
147 segment.template construct<MyShmMultiMap>("MyShmMultiMap3")
148 ( ordered_range
149 , ::boost::make_move_iterator(&aux_vect3[0])
150 , ::boost::make_move_iterator(aux_vect3 + 50)
151 , std::less<IntType>(), segment.get_segment_manager());
152
153 MyStdMultiMap *stdmultimap3 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50);
154
155 if(!CheckEqualContainers(shmmap3, stdmap3)){
156 std::cout << "Error in construct<MyShmMap>(MyShmMap3)" << std::endl;
157 return 1;
158 }
159 if(!CheckEqualContainers(shmmultimap3, stdmultimap3)){
160 std::cout << "Error in construct<MyShmMultiMap>(MyShmMultiMap3)" << std::endl;
161 return 1;
162 }
163
164 segment.destroy_ptr(shmmap2);
165 segment.destroy_ptr(shmmultimap2);
166 delete stdmap2;
167 delete stdmultimap2;
168 segment.destroy_ptr(shmmap3);
169 segment.destroy_ptr(shmmultimap3);
170 delete stdmap3;
171 delete stdmultimap3;
172 }
173 {
174 //This is really nasty, but we have no other simple choice
175 IntPairType aux_vect[max];
176 for(int i = 0; i < max; ++i){
177 IntType i1(i);
178 IntType i2(i);
179 new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
180 }
181 IntPairType aux_vect3[max];
182 for(int i = 0; i < max; ++i){
183 IntType i1(i);
184 IntType i2(i);
185 new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
186 }
187
188 for(int i = 0; i < max; ++i){
189 shmmap->insert(boost::move(aux_vect[i]));
190 stdmap->insert(StdPairType(i, i));
191 shmmultimap->insert(boost::move(aux_vect3[i]));
192 stdmultimap->insert(StdPairType(i, i));
193 }
194
195 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
196 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
197
198 typename MyShmMap::iterator it;
199 typename MyShmMap::const_iterator cit = it;
200 (void)cit;
201
202 shmmap->erase(shmmap->begin()++);
203 stdmap->erase(stdmap->begin()++);
204 shmmultimap->erase(shmmultimap->begin()++);
205 stdmultimap->erase(stdmultimap->begin()++);
206 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
207 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
208
209 shmmap->erase(shmmap->begin());
210 stdmap->erase(stdmap->begin());
211 shmmultimap->erase(shmmultimap->begin());
212 stdmultimap->erase(stdmultimap->begin());
213 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
214 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
215
216 //Swapping test
217 std::less<IntType> lessfunc;
218 MyShmMap tmpshmemap2 (lessfunc, segment.get_segment_manager());
219 MyStdMap tmpstdmap2;
220 MyShmMultiMap tmpshmemultimap2(lessfunc, segment.get_segment_manager());
221 MyStdMultiMap tmpstdmultimap2;
222 shmmap->swap(tmpshmemap2);
223 stdmap->swap(tmpstdmap2);
224 shmmultimap->swap(tmpshmemultimap2);
225 stdmultimap->swap(tmpstdmultimap2);
226 shmmap->swap(tmpshmemap2);
227 stdmap->swap(tmpstdmap2);
228 shmmultimap->swap(tmpshmemultimap2);
229 stdmultimap->swap(tmpstdmultimap2);
230 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
231 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
232 }
233 //Insertion from other container
234 //Initialize values
235 {
236 //This is really nasty, but we have no other simple choice
237 IntPairType aux_vect[50];
238 for(int i = 0; i < 50; ++i){
239 IntType i1(-1);
240 IntType i2(-1);
241 new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
242 }
243 IntPairType aux_vect3[50];
244 for(int i = 0; i < 50; ++i){
245 IntType i1(-1);
246 IntType i2(-1);
247 new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
248 }
249
250 shmmap->insert(::boost::make_move_iterator(&aux_vect[0]), ::boost::make_move_iterator(aux_vect + 50));
251 shmmultimap->insert(::boost::make_move_iterator(&aux_vect3[0]), ::boost::make_move_iterator(aux_vect3 + 50));
252 for(std::size_t i = 0; i != 50; ++i){
253 StdPairType stdpairtype(-1, -1);
254 stdmap->insert(stdpairtype);
255 stdmultimap->insert(stdpairtype);
256 }
257 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
258 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
259
260 for(int i = 0, j = static_cast<int>(shmmap->size()); i < j; ++i){
261 shmmap->erase(IntType(i));
262 stdmap->erase(i);
263 shmmultimap->erase(IntType(i));
264 stdmultimap->erase(i);
265 }
266 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
267 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
268 }
269 {
270 IntPairType aux_vect[50];
271 for(int i = 0; i < 50; ++i){
272 IntType i1(-1);
273 IntType i2(-1);
274 new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
275 }
276
277 IntPairType aux_vect3[50];
278 for(int i = 0; i < 50; ++i){
279 IntType i1(-1);
280 IntType i2(-1);
281 new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
282 }
283
284 IntPairType aux_vect4[50];
285 for(int i = 0; i < 50; ++i){
286 IntType i1(-1);
287 IntType i2(-1);
288 new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2));
289 }
290
291 IntPairType aux_vect5[50];
292 for(int i = 0; i < 50; ++i){
293 IntType i1(-1);
294 IntType i2(-1);
295 new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2));
296 }
297
298 shmmap->insert(::boost::make_move_iterator(&aux_vect[0]), ::boost::make_move_iterator(aux_vect + 50));
299 shmmap->insert(::boost::make_move_iterator(&aux_vect3[0]), ::boost::make_move_iterator(aux_vect3 + 50));
300 shmmultimap->insert(::boost::make_move_iterator(&aux_vect4[0]), ::boost::make_move_iterator(aux_vect4 + 50));
301 shmmultimap->insert(::boost::make_move_iterator(&aux_vect5[0]), ::boost::make_move_iterator(aux_vect5 + 50));
302
303 for(std::size_t i = 0; i != 50; ++i){
304 StdPairType stdpairtype(-1, -1);
305 stdmap->insert(stdpairtype);
306 stdmultimap->insert(stdpairtype);
307 stdmap->insert(stdpairtype);
308 stdmultimap->insert(stdpairtype);
309 }
310 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
311 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
312
313 shmmap->erase(shmmap->begin()->first);
314 stdmap->erase(stdmap->begin()->first);
315 shmmultimap->erase(shmmultimap->begin()->first);
316 stdmultimap->erase(stdmultimap->begin()->first);
317 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
318 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
319 }
320
321 {
322 //This is really nasty, but we have no other simple choice
323 IntPairType aux_vect[max];
324 for(int i = 0; i < max; ++i){
325 IntType i1(i);
326 IntType i2(i);
327 new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
328 }
329 IntPairType aux_vect3[max];
330 for(int i = 0; i < max; ++i){
331 IntType i1(i);
332 IntType i2(i);
333 new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
334 }
335
336 for(int i = 0; i < max; ++i){
337 shmmap->insert(boost::move(aux_vect[i]));
338 stdmap->insert(StdPairType(i, i));
339 shmmultimap->insert(boost::move(aux_vect3[i]));
340 stdmultimap->insert(StdPairType(i, i));
341 }
342
343 if(!CheckEqualPairContainers(shmmap, stdmap)) return 1;
344 if(!CheckEqualPairContainers(shmmultimap, stdmultimap)) return 1;
345
346 for(int i = 0; i < max; ++i){
347 IntPairType intpair;
348 {
349 IntType i1(i);
350 IntType i2(i);
351 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
352 }
353 shmmap->insert(shmmap->begin(), boost::move(intpair));
354 stdmap->insert(stdmap->begin(), StdPairType(i, i));
355 //PrintContainers(shmmap, stdmap);
356 {
357 IntType i1(i);
358 IntType i2(i);
359 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
360 }
361 shmmultimap->insert(shmmultimap->begin(), boost::move(intpair));
362 stdmultimap->insert(stdmultimap->begin(), StdPairType(i, i));
363 //PrintContainers(shmmultimap, stdmultimap);
364 if(!CheckEqualPairContainers(shmmap, stdmap))
365 return 1;
366 if(!CheckEqualPairContainers(shmmultimap, stdmultimap))
367 return 1;
368 {
369 IntType i1(i);
370 IntType i2(i);
371 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
372 }
373 shmmap->insert(shmmap->end(), boost::move(intpair));
374 stdmap->insert(stdmap->end(), StdPairType(i, i));
375 {
376 IntType i1(i);
377 IntType i2(i);
378 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
379 }
380 shmmultimap->insert(shmmultimap->end(), boost::move(intpair));
381 stdmultimap->insert(stdmultimap->end(), StdPairType(i, i));
382 if(!CheckEqualPairContainers(shmmap, stdmap))
383 return 1;
384 if(!CheckEqualPairContainers(shmmultimap, stdmultimap))
385 return 1;
386 {
387 IntType i1(i);
388 IntType i2(i);
389 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
390 }
391 shmmap->insert(shmmap->lower_bound(IntType(i)), boost::move(intpair));
392 stdmap->insert(stdmap->lower_bound(i), StdPairType(i, i));
393 //PrintContainers(shmmap, stdmap);
394 {
395 IntType i1(i);
396 IntType i2(i);
397 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
398 }
399 {
400 IntType i1(i);
401 shmmultimap->insert(shmmultimap->lower_bound(boost::move(i1)), boost::move(intpair));
402 stdmultimap->insert(stdmultimap->lower_bound(i), StdPairType(i, i));
403 }
404
405 //PrintContainers(shmmultimap, stdmultimap);
406 if(!CheckEqualPairContainers(shmmap, stdmap))
407 return 1;
408 if(!CheckEqualPairContainers(shmmultimap, stdmultimap))
409 return 1;
410 {
411 IntType i1(i);
412 IntType i2(i);
413 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
414 }
415 {
416 IntType i1(i);
417 shmmap->insert(shmmap->upper_bound(boost::move(i1)), boost::move(intpair));
418 stdmap->insert(stdmap->upper_bound(i), StdPairType(i, i));
419 }
420 //PrintContainers(shmmap, stdmap);
421 {
422 IntType i1(i);
423 IntType i2(i);
424 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
425 }
426 {
427 IntType i1(i);
428 shmmultimap->insert(shmmultimap->upper_bound(boost::move(i1)), boost::move(intpair));
429 stdmultimap->insert(stdmultimap->upper_bound(i), StdPairType(i, i));
430 }
431 //PrintContainers(shmmultimap, stdmultimap);
432 if(!CheckEqualPairContainers(shmmap, stdmap))
433 return 1;
434 if(!CheckEqualPairContainers(shmmultimap, stdmultimap))
435 return 1;
436 }
437
438 //Compare count with std containers
439 for(int i = 0; i < max; ++i){
440 if(shmmap->count(IntType(i)) != stdmap->count(i)){
441 return -1;
442 }
443
444 if(shmmultimap->count(IntType(i)) != stdmultimap->count(i)){
445 return -1;
446 }
447 }
448
449 //Now do count exercise
450 shmmap->erase(shmmap->begin(), shmmap->end());
451 shmmultimap->erase(shmmultimap->begin(), shmmultimap->end());
452 shmmap->clear();
453 shmmultimap->clear();
454
455 for(int j = 0; j < 3; ++j)
456 for(int i = 0; i < 100; ++i){
457 IntPairType intpair;
458 {
459 IntType i1(i), i2(i);
460 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
461 }
462 shmmap->insert(boost::move(intpair));
463 {
464 IntType i1(i), i2(i);
465 new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
466 }
467 shmmultimap->insert(boost::move(intpair));
468 if(shmmap->count(IntType(i)) != typename MyShmMultiMap::size_type(1))
469 return 1;
470 if(shmmultimap->count(IntType(i)) != typename MyShmMultiMap::size_type(j+1))
471 return 1;
472 }
473 }
474
475 segment.template destroy<MyShmMap>("MyShmMap");
476 delete stdmap;
477 segment.destroy_ptr(shmmultimap);
478 delete stdmultimap;
479
480 segment.shrink_to_fit_indexes();
481
482 if(!segment.all_memory_deallocated())
483 return 1;
484 }
485 catch(...){
486 shared_memory_object::remove(shMemName);
487 throw;
488 }
489 shared_memory_object::remove(shMemName);
490 return 0;
491 }
492
493 template<class ManagedSharedMemory
494 ,class MyShmMap
495 ,class MyStdMap
496 ,class MyShmMultiMap
497 ,class MyStdMultiMap>
map_test_copyable()498 int map_test_copyable ()
499 {
500 typedef typename MyShmMap::key_type IntType;
501 typedef boost::interprocess::pair<IntType, IntType> IntPairType;
502 typedef typename MyStdMap::value_type StdPairType;
503
504 const int memsize = 65536;
505 const char *const shMemName = test::get_process_id_name();
506 const int max = 100;
507
508 try{
509 //Create shared memory
510 shared_memory_object::remove(shMemName);
511 ManagedSharedMemory segment(create_only, shMemName, memsize);
512
513 segment.reserve_named_objects(100);
514
515 //Shared memory allocator must be always be initialized
516 //since it has no default constructor
517 MyShmMap *shmmap =
518 segment.template construct<MyShmMap>("MyShmMap")
519 (std::less<IntType>(), segment.get_segment_manager());
520
521 MyStdMap *stdmap = new MyStdMap;
522
523 MyShmMultiMap *shmmultimap =
524 segment.template construct<MyShmMultiMap>("MyShmMultiMap")
525 (std::less<IntType>(), segment.get_segment_manager());
526
527 MyStdMultiMap *stdmultimap = new MyStdMultiMap;
528
529 int i;
530 for(i = 0; i < max; ++i){
531 {
532 IntType i1(i), i2(i);
533 IntPairType intpair1(boost::move(i1), boost::move(i2));
534 shmmap->insert(boost::move(intpair1));
535 stdmap->insert(StdPairType(i, i));
536 }
537 {
538 IntType i1(i), i2(i);
539 IntPairType intpair2(boost::move(i1), boost::move(i2));
540 shmmultimap->insert(boost::move(intpair2));
541 stdmultimap->insert(StdPairType(i, i));
542 }
543 }
544 if(!CheckEqualContainers(shmmap, stdmap)) return 1;
545 if(!CheckEqualContainers(shmmultimap, stdmultimap)) return 1;
546
547 {
548 //Now, test copy constructor
549 MyShmMap shmmapcopy(*shmmap);
550 MyStdMap stdmapcopy(*stdmap);
551 MyShmMultiMap shmmmapcopy(*shmmultimap);
552 MyStdMultiMap stdmmapcopy(*stdmultimap);
553
554 if(!CheckEqualContainers(&shmmapcopy, &stdmapcopy))
555 return 1;
556 if(!CheckEqualContainers(&shmmmapcopy, &stdmmapcopy))
557 return 1;
558
559 //And now assignment
560 shmmapcopy = *shmmap;
561 stdmapcopy = *stdmap;
562 shmmmapcopy = *shmmultimap;
563 stdmmapcopy = *stdmultimap;
564
565 if(!CheckEqualContainers(&shmmapcopy, &stdmapcopy))
566 return 1;
567 if(!CheckEqualContainers(&shmmmapcopy, &stdmmapcopy))
568 return 1;
569 delete stdmap;
570 delete stdmultimap;
571 segment.destroy_ptr(shmmap);
572 segment.destroy_ptr(shmmultimap);
573 }
574 segment.shrink_to_fit_indexes();
575
576 if(!segment.all_memory_deallocated())
577 return 1;
578 }
579 catch(...){
580 shared_memory_object::remove(shMemName);
581 throw;
582 }
583 shared_memory_object::remove(shMemName);
584 return 0;
585 }
586
587 } //namespace test{
588 } //namespace interprocess{
589 } //namespace boost{
590
591 #include <boost/interprocess/detail/config_end.hpp>
592
593 #endif //#ifndef BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER
594