123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 |
- #include <boost/interprocess/indexes/flat_map_index.hpp>
- #include <boost/interprocess/indexes/map_index.hpp>
- #include <boost/interprocess/indexes/null_index.hpp>
- #include <boost/interprocess/indexes/unordered_map_index.hpp>
- #include <boost/interprocess/indexes/iset_index.hpp>
- #include <boost/interprocess/indexes/iunordered_set_index.hpp>
- #include <boost/interprocess/mem_algo/simple_seq_fit.hpp>
- #include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
- #include <boost/interprocess/mapped_region.hpp>
- #include <boost/interprocess/segment_manager.hpp>
- #include <boost/interprocess/shared_memory_object.hpp>
- #include <boost/interprocess/sync/mutex_family.hpp>
- #include <boost/interprocess/exceptions.hpp>
- #include "get_process_id_name.hpp"
- #include <cstddef>
- #include <new>
- #include <cstring>
- using namespace boost::interprocess;
- template <class SegmentManager>
- struct atomic_func_test
- {
- SegmentManager &rsm;
- int *object;
- atomic_func_test(SegmentManager &sm)
- : rsm(sm), object()
- {}
- void operator()()
- {
- object = rsm.template find<int>("atomic_func_find_object").first;
- }
- private:
- atomic_func_test operator=(const atomic_func_test&);
- atomic_func_test(const atomic_func_test&);
- };
- template <class SegmentManager>
- 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<std::size_t>
- (static_cast<const char *>(mem) - static_cast<const char *>(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<std::size_t>
- (static_cast<const char *>(mem2) - static_cast<const char *>(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<unsigned char *>(mem);
- unsigned char *const mem2_uch_ptr = static_cast<unsigned char *>(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<int>(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<int>(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<int>(anonymous_instance)[ShmSizeSize](); }catch(interprocess_exception&){}
- if(seg_mgr->template construct<int>(anonymous_instance, std::nothrow)[ShmSizeSize]())
- try{ seg_mgr->template construct_it<int>(anonymous_instance)[ShmSizeSize](&int_array_values[0]); }catch(interprocess_exception&){}
- if(seg_mgr->template construct_it<int>(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<unsigned int>(object1_name).first)
- return false;
- //Single element construction
- unsigned int *uint_object = 0;
- switch(i){
- case 0:
- uint_object = seg_mgr->template construct<unsigned int>(object1_name)();
- break;
- case 1:
- uint_object = seg_mgr->template construct<unsigned int>(object1_name, std::nothrow)();
- break;
- case 2:
- uint_object = seg_mgr->template find_or_construct<unsigned int>(object1_name)();
- break;
- case 3:
- uint_object = seg_mgr->template find_or_construct<unsigned int>(object1_name, std::nothrow)();
- break;
- }
- std::pair<unsigned int*, std::size_t> find_ret = seg_mgr->template find<unsigned int>(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<int>(object2_name).first)
- return false;
- int *int_array = 0;
- switch(i){
- case 0:
- int_array = seg_mgr->template construct_it<int>(object2_name)[10](&int_array_values[0]);
- break;
- case 1:
- int_array = seg_mgr->template construct_it<int>(object2_name, std::nothrow)[10](&int_array_values[0]);
- break;
- case 2:
- int_array = seg_mgr->template find_or_construct_it<int>(object2_name)[10](&int_array_values[0]);
- break;
- case 3:
- int_array = seg_mgr->template find_or_construct_it<int>(object2_name, std::nothrow)[10](&int_array_values[0]);
- break;
- }
- std::pair<int*, std::size_t> find_ret2 = seg_mgr->template find<int>(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<int>(object2_name);
- }
- try{ seg_mgr->template construct<unsigned int>(object1_name)[ShmSizeSize](); }catch(interprocess_exception&){}
- if(seg_mgr->template construct<int>(object2_name, std::nothrow)[ShmSizeSize]())
- try{ seg_mgr->template construct_it<unsigned int>(object1_name)[ShmSizeSize](&int_array_values[0]); }catch(interprocess_exception&){}
- if(seg_mgr->template construct_it<int>(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<unsigned int>(unique_instance).first)
- return false;
- //Single element construction
- unsigned int *uint_object = 0;
- switch(i){
- case 0:
- uint_object = seg_mgr->template construct<unsigned int>(unique_instance)();
- break;
- case 1:
- uint_object = seg_mgr->template construct<unsigned int>(unique_instance, std::nothrow)();
- break;
- case 2:
- uint_object = seg_mgr->template find_or_construct<unsigned int>(unique_instance)();
- break;
- case 3:
- uint_object = seg_mgr->template find_or_construct<unsigned int>(unique_instance, std::nothrow)();
- break;
- }
- std::pair<unsigned int*, std::size_t> find_ret = seg_mgr->template find<unsigned int>(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<int>(unique_instance).first)
- return false;
- int *int_array = 0;
- switch(i){
- case 0:
- int_array = seg_mgr->template construct_it<int>(unique_instance)[10](&int_array_values[0]);
- break;
- case 1:
- int_array = seg_mgr->template construct_it<int>(unique_instance, std::nothrow)[10](&int_array_values[0]);
- break;
- case 2:
- int_array = seg_mgr->template find_or_construct_it<int>(unique_instance)[10](&int_array_values[0]);
- break;
- case 3:
- int_array = seg_mgr->template find_or_construct_it<int>(unique_instance, std::nothrow)[10](&int_array_values[0]);
- break;
- }
- std::pair<int*, std::size_t> find_ret2 = seg_mgr->template find<int>(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<int>(unique_instance);
- }
- try{ seg_mgr->template construct<unsigned int>(unique_instance)[ShmSizeSize](); }catch(interprocess_exception&){}
- if(seg_mgr->template construct<int>(unique_instance, std::nothrow)[ShmSizeSize]())
- try{ seg_mgr->template construct_it<unsigned int>(unique_instance)[ShmSizeSize](&int_array_values[0]); }catch(interprocess_exception&){}
- if(seg_mgr->template construct_it<int>(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<float>::type allocator_t;
- allocator_t alloc(seg_mgr->template get_allocator<float>());
- if(!seg_mgr->all_memory_deallocated())
- return false;
- offset_ptr<float> 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<float>::type deleter_t;
- deleter_t delet(seg_mgr->template get_deleter<float>());
- delet(seg_mgr->template construct<float>(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<int>("atomic_func_find_object")();
- atomic_func_test<SegmentManager> 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<class MemoryAlgorithm>
- bool test_each_algo()
- {
- {
- typedef segment_manager< char, MemoryAlgorithm, flat_map_index > segment_manager_t;
- if(!test_segment_manager<segment_manager_t>())
- return false;
- }
- {
- typedef segment_manager< char, MemoryAlgorithm, map_index > segment_manager_t;
- if(!test_segment_manager<segment_manager_t>())
- return false;
- }
- /*
- {
- typedef segment_manager< char, MemoryAlgorithm, null_index > segment_manager_t;
- if(!test_segment_manager<segment_manager_t>())
- return false;
- }*/
- /*
- {
- typedef segment_manager< char, MemoryAlgorithm, unordered_map_index > segment_manager_t;
- if(!test_segment_manager<segment_manager_t>())
- return false;
- }*/
- {
- typedef segment_manager< char, MemoryAlgorithm, iset_index > segment_manager_t;
- if(!test_segment_manager<segment_manager_t>())
- return false;
- }
- {
- typedef segment_manager< char, MemoryAlgorithm, iunordered_set_index > segment_manager_t;
- if(!test_segment_manager<segment_manager_t>())
- 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;
- }
|