c++ - want to efficiently overcome mismatch between key types in a map in Boost.Interprocess shared memory -


i'm creating map (from string string in example) in shared memory using boost.interprocess. compiler seems want force me, during retrieval map, allocate memory in managed segment (unnecessarily) contain query term.

i'd able values in shared map more efficiently, matching map's keys against instances in non-shared memory, without performing allocation. it's refusing compile if try use std::string or const char * argument map's find method. (see compiler error messages @ bottom).

do need define sort of comparator method between shared-memory key type , non-shared equivalent (std::string in example)? if so, should , how should make map use it? if not, should do?

here's code, followed compiler errors. problem towards bottom of main().

// shmap2.cpp  #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp>  //typedefs of allocators , containers namespace shared {     typedef boost::interprocess::managed_shared_memory         segment;      typedef boost::interprocess::managed_shared_memory::segment_manager         segmentmanager;      typedef boost::interprocess::allocator< void, segmentmanager >         allocator;      typedef boost::interprocess::allocator< char, segmentmanager >         charallocator;      typedef boost::interprocess::basic_string< char, std::char_traits< char >, charallocator >          string;      typedef std::less< string >         stringcomparator;      // definition of shared map string string     // (to avoid confusion, let's strictly use python-like definitions of "key", "value" , "item")     typedef std::pair< const string, string >         mapitem;      typedef boost::interprocess::allocator< mapitem, segmentmanager >         mapitemallocator;      typedef boost::interprocess::map< string, string, stringcomparator, mapitemallocator >         map; }  int main( void ) {     struct shm_remove     {         shm_remove() { boost::interprocess::shared_memory_object::remove( "mysharedmemory" ); }         ~shm_remove(){ boost::interprocess::shared_memory_object::remove( "mysharedmemory" ); }     } remover;      // create shared memory     shared::segment seg( boost::interprocess::create_only, "mysharedmemory", 65536 );      // allocator instance can converted allocator< t, shared::segmentmanager > type     shared::allocator alloc( seg.get_segment_manager() );      // instance of string comparator, construct map     shared::stringcomparator cmp;      // construct shared memory map     shared::map * mymapptr = seg.construct< shared::map >( "mymap" )( cmp, alloc );      // here's problem:      // std::string key( "foo" );            // compilation fails if use this.     // char key[] = "foo";                  // compilation fails if use this.     shared::string key( "foo", alloc );     // version can work.                                             // forces create copy of                                             // key searching for, in                                             // managed segment.      // point of exercise:     shared::map::iterator = mymapptr->find( key );      return 0; } 

with std::string key:

$ g++ -o shmap2 -d boost_all_no_lib  -i ../boost_1_57_0  shmap2.cpp shmap2.cpp:79:40: error: no matching member function call 'find'                 shared::map::iterator = mymapptr->find( key );                                            ~~~~~~~~~~^~~~ ../boost_1_57_0/boost/container/detail/tree.hpp:1089:13: note: candidate function not       viable: no known conversion 'std::string' (aka 'basic_string<char,       char_traits<char>, allocator<char> >') 'const key_type' (aka 'const       boost::container::basic_string<char, std::__1::char_traits<char>,       boost::interprocess::allocator<char, boost::interprocess::segment_manager<char,       boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,       boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >       >') 1st argument    iterator find(const key_type& k)             ^ ../boost_1_57_0/boost/container/detail/tree.hpp:1092:19: note: candidate function not       viable: no known conversion 'std::string' (aka 'basic_string<char,       char_traits<char>, allocator<char> >') 'const key_type' (aka 'const       boost::container::basic_string<char, std::__1::char_traits<char>,       boost::interprocess::allocator<char, boost::interprocess::segment_manager<char,       boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,       boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >       >') 1st argument    const_iterator find(const key_type& k) const                   ^ 1 error generated. 

with const char * key:

$ g++ -o shmap2 -d boost_all_no_lib  -i ../boost_1_57_0  shmap2.cpp in file included shmap2.cpp:17: in file included ../boost_1_57_0/boost/interprocess/containers/string.hpp:19: ../boost_1_57_0/boost/container/string.hpp:676:59: error: no matching constructor       initialization of 'allocator_type' (aka 'boost::interprocess::allocator<char,       boost::interprocess::segment_manager<char,       boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,       boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> >')    basic_string(const chart* s, const allocator_type& = allocator_type())                                                           ^ shmap2.cpp:79:46: note: in instantiation of default function argument expression       'basic_string<char, std::__1::char_traits<char>, boost::interprocess::allocator<char,       boost::interprocess::segment_manager<char,       boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family,       boost::interprocess::offset_ptr<void, long, unsigned long, 0>, 0>, iset_index> > >'       required here                 shared::map::iterator = mymapptr->find( key );                                                            ^ ../boost_1_57_0/boost/interprocess/allocators/allocator.hpp:140:4: note: candidate       constructor template not viable: requires single argument 'other', no       arguments provided    allocator(const allocator<t2, segmentmanager> &other)    ^ ../boost_1_57_0/boost/interprocess/allocators/allocator.hpp:129:4: note: candidate      constructor not viable: requires single argument 'segment_mngr', no arguments      provided    allocator(segment_manager *segment_mngr)    ^ ../boost_1_57_0/boost/interprocess/allocators/allocator.hpp:134:4: note: candidate      constructor not viable: requires single argument 'other', no arguments      provided    allocator(const allocator &other)    ^ 1 error generated. 

update: following suggestion of sehe, below, tried replacing

typedef std::less< string >     stringcomparator; 

with

typedef struct {     template< typename t, typename u >     bool operator()( const t & t, const u & u )         const { return t < u; } } stringcomparator; 

but got same 2 compiler errors.

you can use custom comparator

   struct myless {         template <typename t, typename u>             bool operator()(const t&t, const u&u) const         {             return t<u;         }     }; 

in code can typedef stringcomparator

update comments


multi index rescue

if want replace std::map/boost::container::map boost multi index container (which supports lookup compatiblekey), here's demo of how it:

i've borrowed of idea's documentation section emulating standard containers multi_index_container.

note std::string lookup key still won't work, can use .c_strio() in event.

live on coliru

#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp>  #include <boost/multi_index_container.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/member.hpp>  namespace emulation {     template <typename t1,typename t2,typename alloc>         struct mutable_pair         {             typedef t1 first_type;             typedef t2 second_type;              mutable_pair(alloc alloc):first(t1(alloc)),second(t2(alloc)){}             mutable_pair(const t1& f,const t2& s):first(f),second(s){}             mutable_pair(const std::pair<t1,t2>& p):first(p.first),second(p.second){}              t1         first;             mutable t2 second;         };      using namespace boost::multi_index;      template <typename key, typename t, typename compare, typename allocator, typename element = mutable_pair<key, t, allocator> >         using map = multi_index_container<             element,             indexed_by<                 ordered_unique<member<element,key,&element::first>,compare>             >,             typename allocator::template rebind<element>::other         >;    template <typename key, typename t, typename compare, typename allocator, typename element = mutable_pair<key, t, allocator> >     using multimap = multi_index_container<         element,         indexed_by<             ordered_non_unique<member<element,key,&element::first>,compare>         >,         typename allocator::template rebind<element>::other     >;    template <typename key, typename t, typename compare, typename allocator>        struct wrap_map : map<key, t, compare, allocator> {           typedef map<key, t, compare, allocator> base_type;           typedef typename base_type::template nth_index<0>::type index_type;            wrap_map(allocator alloc) : base_type({}, alloc)           {           }            wrap_map(compare cmp, allocator alloc) : base_type(                   typename base_type::ctor_args_list{                     typename index_type::ctor_args { typename index_type::key_from_value {}, cmp }                   },                   alloc)           {           }       }; }  // typedefs of allocators , containers namespace shared {     typedef boost::interprocess::managed_shared_memory segment;     typedef boost::interprocess::managed_shared_memory::segment_manager segmentmanager;     typedef boost::interprocess::allocator<void, segmentmanager> allocator;     typedef boost::interprocess::allocator<char, segmentmanager> charallocator;     typedef boost::interprocess::basic_string<char, std::char_traits<char>, charallocator> string;      struct myless {         template <typename t, typename u> bool operator()(const t &t, const u &u) const { return t < u; }     };     typedef myless stringcomparator;       typedef boost::interprocess::allocator<char, segmentmanager> stringalloc;     typedef emulation::mutable_pair<const string, string, stringalloc> mapitem;     typedef boost::interprocess::allocator<mapitem, segmentmanager> mapitemallocator;     typedef emulation::wrap_map<string, string, stringcomparator, mapitemallocator> map; }  int main(void) {     struct shm_remove {         shm_remove() { boost::interprocess::shared_memory_object::remove("mysharedmemory"); }         ~shm_remove() { boost::interprocess::shared_memory_object::remove("mysharedmemory"); }     } remover;      // create shared memory     shared::segment seg(boost::interprocess::create_only, "mysharedmemory", 65536);     shared::allocator alloc(seg.get_segment_manager());      // instance of string comparator, construct map     shared::stringcomparator cmp;      // construct shared memory map     shared::map *mymapptr = seg.construct<shared::map>("mymap")(cmp, alloc);      mymapptr->emplace(shared::string("foo", alloc), shared::string("bar", alloc));     mymapptr->emplace(shared::string("goo", alloc), shared::string("car", alloc));     mymapptr->emplace(shared::string("hoo", alloc), shared::string("dar", alloc));      shared::string key("foo", alloc);      // point of exercise:     auto = mymapptr->find(key);      if (it!=mymapptr->end())         std::cout << "found: '" << it->first << "' -> '" << it->second << "'\n";      // okay     char szkey[] = "foo";     = mymapptr->find(szkey);     if (it!=mymapptr->end())         std::cout << "found: '" << it->first << "' -> '" << it->second << "'\n";      // okay     std::string skey("foo");     = mymapptr->find(skey.c_str());     if (it!=mymapptr->end())         std::cout << "found: '" << it->first << "' -> '" << it->second << "'\n";      return 0; } 

prints:

found: 'foo' -> 'bar' found: 'foo' -> 'bar' found: 'foo' -> 'bar' 

scoped allocators awesomesauce?

now, interestingly, boost container supports scoped allocators, away repeated passing of allocators, however, boost multi index sadly doesn't support fully. here's halfway approach that's far (still user friendlier):

live on coliru

#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp>  #include <boost/container/scoped_allocator.hpp>  #include <boost/multi_index_container.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/member.hpp>  namespace emulation {     template <typename t1,typename t2,typename alloc>         struct mutable_pair         {             typedef alloc allocator_type;             typedef t1 first_type;             typedef t2 second_type;              mutable_pair(alloc alloc):first(t1(alloc)),second(t2(alloc)){}             mutable_pair(const t1& f,const t2& s):first(f),second(s){}             mutable_pair(const std::pair<t1,t2>& p):first(p.first),second(p.second){}              template <typename u, typename v, typename alloc2>             mutable_pair(const u& f,const v& s, alloc2 alloc):first(f, alloc),second(s, alloc){}              t1         first;             mutable t2 second;         };      using namespace boost::multi_index;      template <typename key, typename t, typename compare, typename allocator, typename element = mutable_pair<key, t, allocator> >         using map = multi_index_container<             element,             indexed_by<                 ordered_unique<member<element,key,&element::first>,compare>             >,             typename allocator::template rebind<element>::other         >;    template <typename key, typename t, typename compare, typename allocator, typename element = mutable_pair<key, t, allocator> >     using multimap = multi_index_container<         element,         indexed_by<             ordered_non_unique<member<element,key,&element::first>,compare>         >,         typename allocator::template rebind<element>::other     >;    template <typename key, typename t, typename compare, typename allocator>        struct wrap_map : map<key, t, compare, allocator> {           typedef map<key, t, compare, allocator> base_type;           typedef typename base_type::template nth_index<0>::type index_type;            wrap_map(allocator alloc) : base_type({}, alloc)           {            }            wrap_map(compare cmp, allocator alloc) : base_type(                   typename base_type::ctor_args_list{                     typename index_type::ctor_args { typename index_type::key_from_value {}, cmp }                   },                   alloc)           {            }       }; }   // typedefs of allocators , containers namespace shared {     typedef boost::interprocess::managed_shared_memory segment;     typedef segment::segment_manager segmentmanager;     typedef boost::container::scoped_allocator_adaptor<boost::interprocess::allocator<void, segmentmanager> > allocator;      typedef allocator::rebind<char>::other charallocator;     typedef boost::interprocess::basic_string<char, std::char_traits<char>, charallocator> string;      struct myless {         template <typename t, typename u> bool operator()(const t &t, const u &u) const { return t < u; }     };     typedef myless stringcomparator;      typedef emulation::mutable_pair<string, string, charallocator> mapitem;     typedef allocator::rebind<mapitem>::other mapitemallocator;     typedef emulation::wrap_map<string, string, stringcomparator, mapitemallocator> map; }  int main(void) {     struct shm_remove {         shm_remove() { boost::interprocess::shared_memory_object::remove("mysharedmemory"); }         ~shm_remove() { boost::interprocess::shared_memory_object::remove("mysharedmemory"); }     } remover;      // create shared memory     shared::segment seg(boost::interprocess::create_only, "mysharedmemory", 65536);     shared::allocator alloc(seg.get_segment_manager());      // instance of string comparator, construct map     shared::stringcomparator cmp;      // construct shared memory map     shared::map *mymapptr = seg.construct<shared::map>("mymap")(cmp, alloc);      mymapptr->emplace("foo", "bar", alloc);     mymapptr->emplace("goo", "car", alloc);     mymapptr->emplace("hoo", "dar", alloc);      // version can work.  forces create     // copy of key searching for, in managed segment.     shared::string key("foo", alloc);           // point of exercise:     auto = mymapptr->find(key);      if (it!=mymapptr->end())         std::cout << "found: '" << it->first << "' -> '" << it->second << "'\n";      // okay     char szkey[] = "foo";     = mymapptr->find(szkey);     if (it!=mymapptr->end())         std::cout << "found: '" << it->first << "' -> '" << it->second << "'\n";      // okay     std::string skey("foo");     = mymapptr->find(skey.c_str());     if (it!=mymapptr->end())         std::cout << "found: '" << it->first << "' -> '" << it->second << "'\n";      return 0; } 

also printing

found: 'foo' -> 'bar' found: 'foo' -> 'bar' found: 'foo' -> 'bar' 

Comments

Popular posts from this blog

python - mat is not a numerical tuple : openCV error -

c# - MSAA finds controls UI Automation doesn't -

wordpress - .htaccess: RewriteRule: bad flag delimiters -