segment_manager_test.cpp 19 KB

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