#include #include #include #include #include #include #include #include #include #include #include #include #include #include "get_process_id_name.hpp" #include #include #include using namespace boost::interprocess; template struct atomic_func_test { SegmentManager &rsm; int *object; atomic_func_test(SegmentManager &sm) : rsm(sm), object() {} void operator()() { object = rsm.template find("atomic_func_find_object").first; } private: atomic_func_test operator=(const atomic_func_test&); atomic_func_test(const atomic_func_test&); }; template bool test_segment_manager() { typedef typename SegmentManager::size_type size_type; const unsigned int ShmSizeSize = 1024*64u; std::string shmname(test::get_process_id_name()); shared_memory_object::remove(shmname.c_str()); shared_memory_object sh_mem( create_only, shmname.c_str(), read_write ); sh_mem.truncate( ShmSizeSize ); mapped_region mapping( sh_mem, read_write ); SegmentManager* seg_mgr = new( mapping.get_address() ) SegmentManager( ShmSizeSize ); std::size_t free_mem_before = seg_mgr->get_free_memory(); std::size_t size_before = seg_mgr->get_size(); if(size_before != ShmSizeSize) return false; if(!seg_mgr->all_memory_deallocated()) return false; if(seg_mgr->get_min_size() >= ShmSizeSize) return false; {//test get_free_memory() / allocate()/deallocate() const size_type Size = ShmSizeSize/2; void *mem = seg_mgr->allocate(Size+1); const size_type free_mem = seg_mgr->get_free_memory(); if(free_mem >= Size) return false; if(seg_mgr->all_memory_deallocated()) return false; const size_type Size2 = free_mem/2; void *mem2 = seg_mgr->allocate(size_type(Size2+1), std::nothrow); if(seg_mgr->get_free_memory() >= Size2) return false; if(seg_mgr->size(mem) < (Size+1)) return false; if(seg_mgr->size(mem2) < (Size2+1)) return false; seg_mgr->deallocate(mem); seg_mgr->deallocate(mem2); if(!seg_mgr->all_memory_deallocated()) return false; if(seg_mgr->get_free_memory() != free_mem_before) return false; try{ seg_mgr->allocate(ShmSizeSize*2); }catch(interprocess_exception&){} if(seg_mgr->get_free_memory() != free_mem_before) return false; if(seg_mgr->allocate(ShmSizeSize*2, std::nothrow)) return false; if(seg_mgr->get_free_memory() != free_mem_before) return false; } {//test allocate_aligned const std::size_t Alignment = 128u; void *mem = seg_mgr->allocate_aligned(ShmSizeSize/4, Alignment); if(seg_mgr->all_memory_deallocated()) return false; std::size_t offset = static_cast (static_cast(mem) - static_cast(mapping.get_address())); if(offset & (Alignment-1)) return false; void *mem2 = seg_mgr->allocate_aligned(ShmSizeSize/4, Alignment, std::nothrow); std::size_t offset2 = static_cast (static_cast(mem2) - static_cast(mapping.get_address())); if(offset2 & (Alignment-1)) return false; seg_mgr->deallocate(mem); seg_mgr->deallocate(mem2); if(!seg_mgr->all_memory_deallocated()) return false; if(seg_mgr->get_free_memory() != free_mem_before) return false; try{ seg_mgr->allocate_aligned(ShmSizeSize*2, Alignment); }catch(interprocess_exception&){} if(seg_mgr->get_free_memory() != free_mem_before) return false; if(seg_mgr->allocate_aligned(ShmSizeSize*2, Alignment, std::nothrow)) return false; if(seg_mgr->get_free_memory() != free_mem_before) return false; } {//test shrink_to_fit seg_mgr->shrink_to_fit(); if(!seg_mgr->all_memory_deallocated()) return false; std::size_t empty_shrunk_size = seg_mgr->get_size(); std::size_t empty_shrunk_free_mem = seg_mgr->get_free_memory(); if(empty_shrunk_size >= size_before) return false; if(empty_shrunk_free_mem >= size_before) return false; seg_mgr->grow(size_type(size_before - empty_shrunk_size)); if(seg_mgr->get_size() != size_before) return false; if(seg_mgr->get_free_memory() != free_mem_before) return false; if(!seg_mgr->all_memory_deallocated()) return false; } {//test zero_free_memory const size_type Size(ShmSizeSize/2+1), Size2(ShmSizeSize/8); void *mem = seg_mgr->allocate(Size); void *mem2 = seg_mgr->allocate(Size2); //Mark memory to non-zero std::memset(mem, 0xFF, Size); std::memset(mem2, 0xFF, Size2); //Deallocate and check still non-zero seg_mgr->deallocate(mem); seg_mgr->deallocate(mem2); { //Use byte per byte comparison as "static unsigned char zerobuf[Size]" //seems to be problematic in some compilers unsigned char *const mem_uch_ptr = static_cast(mem); unsigned char *const mem2_uch_ptr = static_cast(mem2); size_type zeroes = 0; for(size_type i = 0; i != Size; ++i){ if(!mem_uch_ptr[i]) ++zeroes; } if(zeroes == Size) return false; zeroes = 0; for(size_type i = 0; i != Size2; ++i){ if(!mem2_uch_ptr[i]) ++zeroes; } if(zeroes == Size2) return false; } //zero_free_memory and check it's zeroed seg_mgr->zero_free_memory(); //TODO: some parts are not zeroed because they are used //as internal metadata, find a way to test this //if(std::memcmp(mem, zerobuf, Size)) //return false; //if(std::memcmp(mem2, zerobuf, Size2)) //return false; if(seg_mgr->get_free_memory() != free_mem_before) return false; if(!seg_mgr->all_memory_deallocated()) return false; } {//test anonymous object int *int_object = seg_mgr->template construct(anonymous_instance)(); if(1 != seg_mgr->get_instance_length(int_object)) return false; if(anonymous_type != seg_mgr->get_instance_type(int_object)) return false; if(seg_mgr->get_instance_name(int_object)) return false; seg_mgr->destroy_ptr(int_object); int const int_array_values[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int *int_array = seg_mgr->template construct_it(anonymous_instance, std::nothrow)[10](&int_array_values[0]); if(10 != seg_mgr->get_instance_length(int_object)) return false; if(anonymous_type != seg_mgr->get_instance_type(int_array)) return false; if(seg_mgr->get_instance_name(int_array)) return false; seg_mgr->destroy_ptr(int_array); try{ seg_mgr->template construct(anonymous_instance)[ShmSizeSize](); }catch(interprocess_exception&){} if(seg_mgr->template construct(anonymous_instance, std::nothrow)[ShmSizeSize]()) try{ seg_mgr->template construct_it(anonymous_instance)[ShmSizeSize](&int_array_values[0]); }catch(interprocess_exception&){} if(seg_mgr->template construct_it(anonymous_instance, std::nothrow)[ShmSizeSize](&int_array_values[0])) return false; if(seg_mgr->get_free_memory() != free_mem_before) return false; if(!seg_mgr->all_memory_deallocated()) return false; } {//test named object const char *const object1_name = "object1"; const char *const object2_name = "object2"; int const int_array_values[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; for(std::size_t i = 0; i != 1/*4*/; ++i){ if(seg_mgr->template find(object1_name).first) return false; //Single element construction unsigned int *uint_object = 0; switch(i){ case 0: uint_object = seg_mgr->template construct(object1_name)(); break; case 1: uint_object = seg_mgr->template construct(object1_name, std::nothrow)(); break; case 2: uint_object = seg_mgr->template find_or_construct(object1_name)(); break; case 3: uint_object = seg_mgr->template find_or_construct(object1_name, std::nothrow)(); break; } std::pair find_ret = seg_mgr->template find(object1_name); if(uint_object != find_ret.first) return false; if(1 != find_ret.second) return false; if(1 != seg_mgr->get_instance_length(uint_object)) return false; if(named_type != seg_mgr->get_instance_type(uint_object)) return false; if(std::strcmp(object1_name, seg_mgr->get_instance_name(uint_object))) return false; //Array construction if(seg_mgr->template find(object2_name).first) return false; int *int_array = 0; switch(i){ case 0: int_array = seg_mgr->template construct_it(object2_name)[10](&int_array_values[0]); break; case 1: int_array = seg_mgr->template construct_it(object2_name, std::nothrow)[10](&int_array_values[0]); break; case 2: int_array = seg_mgr->template find_or_construct_it(object2_name)[10](&int_array_values[0]); break; case 3: int_array = seg_mgr->template find_or_construct_it(object2_name, std::nothrow)[10](&int_array_values[0]); break; } std::pair find_ret2 = seg_mgr->template find(object2_name); if(int_array != find_ret2.first) return false; if(10 != find_ret2.second) return false; if(10 != seg_mgr->get_instance_length(int_array)) return false; if(named_type != seg_mgr->get_instance_type(int_array)) return false; if(std::strcmp(object2_name, seg_mgr->get_instance_name(int_array))) return false; if(seg_mgr->get_num_named_objects() != 2) return false; typename SegmentManager::const_named_iterator nb(seg_mgr->named_begin()); typename SegmentManager::const_named_iterator ne(seg_mgr->named_end()); for(std::size_t i = 0, imax = seg_mgr->get_num_named_objects(); i != imax; ++i){ ++nb; } if(nb != ne) return false; seg_mgr->destroy_ptr(uint_object); seg_mgr->template destroy(object2_name); } try{ seg_mgr->template construct(object1_name)[ShmSizeSize](); }catch(interprocess_exception&){} if(seg_mgr->template construct(object2_name, std::nothrow)[ShmSizeSize]()) try{ seg_mgr->template construct_it(object1_name)[ShmSizeSize](&int_array_values[0]); }catch(interprocess_exception&){} if(seg_mgr->template construct_it(object2_name, std::nothrow)[ShmSizeSize](&int_array_values[0])) return false; seg_mgr->shrink_to_fit_indexes(); if(seg_mgr->get_free_memory() != free_mem_before) return false; if(!seg_mgr->all_memory_deallocated()) return false; seg_mgr->reserve_named_objects(1); //In indexes with no capacity() memory won't be allocated so don't check anything was allocated. //if(seg_mgr->all_memory_deallocated()) return false; seg_mgr->shrink_to_fit_indexes(); if(!seg_mgr->all_memory_deallocated()) return false; } {//test unique object int const int_array_values[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; for(std::size_t i = 0; i != 4; ++i){ if(seg_mgr->template find(unique_instance).first) return false; //Single element construction unsigned int *uint_object = 0; switch(i){ case 0: uint_object = seg_mgr->template construct(unique_instance)(); break; case 1: uint_object = seg_mgr->template construct(unique_instance, std::nothrow)(); break; case 2: uint_object = seg_mgr->template find_or_construct(unique_instance)(); break; case 3: uint_object = seg_mgr->template find_or_construct(unique_instance, std::nothrow)(); break; } std::pair find_ret = seg_mgr->template find(unique_instance); if(uint_object != find_ret.first) return false; if(1 != find_ret.second) return false; if(1 != seg_mgr->get_instance_length(uint_object)) return false; if(unique_type != seg_mgr->get_instance_type(uint_object)) return false; if(std::strcmp(typeid(unsigned int).name(), seg_mgr->get_instance_name(uint_object))) return false; //Array construction if(seg_mgr->template find(unique_instance).first) return false; int *int_array = 0; switch(i){ case 0: int_array = seg_mgr->template construct_it(unique_instance)[10](&int_array_values[0]); break; case 1: int_array = seg_mgr->template construct_it(unique_instance, std::nothrow)[10](&int_array_values[0]); break; case 2: int_array = seg_mgr->template find_or_construct_it(unique_instance)[10](&int_array_values[0]); break; case 3: int_array = seg_mgr->template find_or_construct_it(unique_instance, std::nothrow)[10](&int_array_values[0]); break; } std::pair find_ret2 = seg_mgr->template find(unique_instance); if(int_array != find_ret2.first) return false; if(10 != find_ret2.second) return false; if(10 != seg_mgr->get_instance_length(int_array)) return false; if(unique_type != seg_mgr->get_instance_type(int_array)) return false; if(std::strcmp(typeid(int).name(), seg_mgr->get_instance_name(int_array))) return false; if(seg_mgr->get_num_unique_objects() != 2) return false; typename SegmentManager::const_unique_iterator nb(seg_mgr->unique_begin()); typename SegmentManager::const_unique_iterator ne(seg_mgr->unique_end()); for(std::size_t i = 0, imax = seg_mgr->get_num_unique_objects(); i != imax; ++i){ ++nb; } if(nb != ne) return false; seg_mgr->destroy_ptr(uint_object); seg_mgr->template destroy(unique_instance); } try{ seg_mgr->template construct(unique_instance)[ShmSizeSize](); }catch(interprocess_exception&){} if(seg_mgr->template construct(unique_instance, std::nothrow)[ShmSizeSize]()) try{ seg_mgr->template construct_it(unique_instance)[ShmSizeSize](&int_array_values[0]); }catch(interprocess_exception&){} if(seg_mgr->template construct_it(unique_instance, std::nothrow)[ShmSizeSize](&int_array_values[0])) return false; seg_mgr->shrink_to_fit_indexes(); if(seg_mgr->get_free_memory() != free_mem_before) return false; if(!seg_mgr->all_memory_deallocated()) return false; seg_mgr->reserve_unique_objects(1); //In indexes with no capacity() memory won't be allocated so don't check anything was allocated. //if(seg_mgr->all_memory_deallocated()) return false; seg_mgr->shrink_to_fit_indexes(); if(!seg_mgr->all_memory_deallocated()) return false; } {//test allocator/deleter if(!seg_mgr->all_memory_deallocated()) return false; typedef typename SegmentManager::template allocator::type allocator_t; allocator_t alloc(seg_mgr->template get_allocator()); if(!seg_mgr->all_memory_deallocated()) return false; offset_ptr f = alloc.allocate(50); if(seg_mgr->all_memory_deallocated()) return false; alloc.deallocate(f, 50); if(!seg_mgr->all_memory_deallocated()) return false; typedef typename SegmentManager::template deleter::type deleter_t; deleter_t delet(seg_mgr->template get_deleter()); delet(seg_mgr->template construct(anonymous_instance)()); if(!seg_mgr->all_memory_deallocated()) return false; } {//test allocator/deleter if(!seg_mgr->all_memory_deallocated()) return false; int *int_object = seg_mgr->template construct("atomic_func_find_object")(); atomic_func_test func(*seg_mgr); seg_mgr->atomic_func(func); if(int_object != func.object) return 1; seg_mgr->destroy_ptr(int_object); seg_mgr->shrink_to_fit_indexes(); if(!seg_mgr->all_memory_deallocated()) return false; } return true; } template bool test_each_algo() { { typedef segment_manager< char, MemoryAlgorithm, flat_map_index > segment_manager_t; if(!test_segment_manager()) return false; } { typedef segment_manager< char, MemoryAlgorithm, map_index > segment_manager_t; if(!test_segment_manager()) return false; } /* { typedef segment_manager< char, MemoryAlgorithm, null_index > segment_manager_t; if(!test_segment_manager()) return false; }*/ /* { typedef segment_manager< char, MemoryAlgorithm, unordered_map_index > segment_manager_t; if(!test_segment_manager()) return false; }*/ { typedef segment_manager< char, MemoryAlgorithm, iset_index > segment_manager_t; if(!test_segment_manager()) return false; } { typedef segment_manager< char, MemoryAlgorithm, iunordered_set_index > segment_manager_t; if(!test_segment_manager()) return false; } return true; } int main() { if(!test_each_algo< simple_seq_fit< null_mutex_family > >()) return 1; if(!test_each_algo< rbtree_best_fit< null_mutex_family > >()) return 1; return 0; }