[interprocess] example for boost::interprocess::map where the key is something in shared memory

does anyone have a simple example of a map in shared memory, where the key is also in shared memory & not a simple "int"? I am trying to use a key of type boost::interprocess::basic_string<wchar_t, ...>, value of type unsigned long, and I am not sure about the subtleties of using boost::interprocess::map<>.insert() where the key lives in shared memory. (the example http://www.boost.org/doc/libs/1_35_0/doc/html/interprocess/quick_guide.html#... is useful but both the key and value are simple types.) If I understand right, you have to insert() an instance of the std::pair<> class. But if the map is in shared memory, does this mean the std::pair<> also has to live in shared memory as well? (vs. a local std::pair<> that exists on the stack) For some reason the basic_string<wchar_t,...> seems to have been instantiated in some other weird area of memory instead & it's very difficult to debug + figure out what's going wrong.

does anyone have a simple example of a map in shared memory, where the key is also in shared memory & not a simple "int"? I am trying to use a key of type boost::interprocess::basic_string<wchar_t, ...>, value of type unsigned long, and I am not sure about the subtleties of using boost::interprocess::map<>.insert() where the key lives in shared memory. (the example http://www.boost.org/doc/libs/1_35_0/doc/html/interprocess/quick_guide.html#... is useful but both the key and value are simple types.) If I understand right, you have to insert() an instance of the std::pair<> class. But if the map is in shared memory, does this mean the std::pair<> also has to live in shared memory as well? (vs. a local std::pair<> that exists on the stack) For some reason the basic_string<wchar_t,...> seems to have been instantiated in some other weird area of memory instead & it's very difficult to debug + figure out what's going wrong.

Jason Sachs wrote:
does anyone have a simple example of a map in shared memory, where the key is also in shared memory & not a simple "int"?
This example will go in the "quick guide for the impatient" section ASAP. ////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2006-2008. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> //[doc_complex_map #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> using namespace boost::interprocess; //Typedefs of allocators and containers typedef managed_shared_memory::segment_manager segment_manager_t; typedef allocator<void, segment_manager_t> void_allocator; typedef allocator<int, segment_manager_t> int_allocator; typedef vector<int, int_allocator> int_vector; typedef allocator<int_vector, segment_manager_t> int_vector_allocator; typedef vector<int_vector, int_vector_allocator> int_vector_vector; typedef allocator<char, segment_manager_t> char_allocator; typedef basic_string<char, std::char_traits<char>, char_allocator> char_string; class complex_data { int id_; char_string char_string_; int_vector_vector int_vector_vector_; public: //Since void_allocator is convertible to any other allocator<T>, we can simplify //the initialization taking just one allocator for all inner containers. complex_data(int id, const char *name, const void_allocator &void_alloc) : id_(id), char_string_(name, void_alloc), int_vector_vector_(void_alloc) {} //Other members... }; //Definition of the map holding a string as key and complex_data as mapped type typedef std::pair<const char_string, complex_data> map_value_type; typedef std::pair<char_string, complex_data> movable_to_map_value_type; typedef allocator<map_value_type, segment_manager_t> map_value_type_allocator; typedef map< char_string, complex_data , std::less<char_string>, map_value_type_allocator> complex_map_type; int main () { shared_memory_object::remove("MySharedMemory"); remove_shared_memory_on_destroy remove_on_destroy("MySharedMemory"); { //Create shared memory managed_shared_memory segment(create_only,"MySharedMemory", 65536); //An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst (segment.get_segment_manager()); //Construct the shared memory map and fill it complex_map_type *mymap = segment.construct<complex_map_type> //(object name), (first ctor parameter, second ctor parameter) ("MyMap")(std::less<char_string>(), alloc_inst); for(int i = 0; i < 100; ++i){ //Both key(string) and value(complex_data) need an allocator in their constructors char_string key_object(alloc_inst); complex_data mapped_object(i, "default_name", alloc_inst); map_value_type value(key_object, mapped_object); //Modify values and insert them in the map mymap->insert(value); } } return 0; } //] #include <boost/interprocess/detail/config_end.hpp>

Ion Gaztañaga <igaztanaga <at> gmail.com> writes:
//An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst (segment.get_segment_manager());
//Construct the shared memory map and fill it complex_map_type *mymap = segment.construct<complex_map_type> //(object name), (first ctor parameter, second ctor parameter) ("MyMap")(std::less<char_string>(), alloc_inst);
for(int i = 0; i < 100; ++i){ //Both key(string) and value(complex_data) need an allocator in their constructors char_string key_object(alloc_inst); complex_data mapped_object(i, "default_name", alloc_inst); map_value_type value(key_object, mapped_object); //Modify values and insert them in the map mymap->insert(value); }
Thanks, that helps. I didn't know you could use void_allocators, I thought they had to be specific for each allocated type. One question: I noticed in the example you posted, that the lifetime of the allocator "alloc_inst" equals/exceeds the lifetime of the map and the values that are inserted into the map. Is this required, or can the allocator just be a temporary stack variable (as follows)? char_string key_object(void_allocator(segment.get_segment_manager()));

Jason Sachs wrote:
Thanks, that helps. I didn't know you could use void_allocators, I thought they had to be specific for each allocated type. One question: I noticed in the example you posted, that the lifetime of the allocator "alloc_inst" equals/exceeds the lifetime of the map and the values that are inserted into the map. Is this required, or can the allocator just be a temporary stack variable (as follows)?
char_string key_object(void_allocator(segment.get_segment_manager()));
Just like standard allocators the container makes an internal copy of the arguments (allocator or comparison function for associative containers), so you can initialize it with a variable in the stack. The goal is to create a container in shared memory and it will hold the allocator internally. Regards, Ion
participants (2)
-
Ion Gaztañaga
-
Jason Sachs