I am a bit confused by the heap and by-value-versus-by-reference semantics involved in putting a std::string
key and a large struct
value into a container like boost::interprocess::map
.
Here is my situation, and some typedefs I'm using:
typedef std::string AreaKeyType;
typedef DATA_AREA_DESC AreaMappedType; // DATA_AREA_DESC is a big struct.
typedef std::pair<const AreaKeyType, AreaMappedType> AreaValueType;
typedef boost::interprocess::allocator<AreaValueType, boost::interprocess::managed_shared_memory::segment_manager> AreaShmemAllocator;
typedef boost::interprocess::map<AreaKeyType, AreaMappedType, std::less<AreaKeyType>, AreaShmemAllocator> AreaMap;
Here is how I'm inserting AreaValueType (which is a typedef for std::pair):
AreaValueType A(areaKey, arearec);
anAreaMap->insert(A);
I believe the above code copies A which is an std::pair on my local (non shared memory) stack into a shared memory area. Can I get a handle to that shared memory area inside the boost::interprocess::map or am I limited to fetching that record back whole and storing it whole? (In other words, can I store something like a structure into a boost interprocess map and then update a single byte inside that record, or do I have to only update the entire record by replacing all the bytes in a DATA_AREA_DESC struct, with entirely new bytes.)
Some further clarification:
I have a plain old ANSI C DLL export api that internally uses C++ and Boost::interprocess::map. The function is expected to create an item in the map and then return a handle. How can I insert something into the boost::interprocess::map and then return a handle to that entity, to non-C++ users, preferably cast to
void*
orunsigned long
? All I can seem to do is fetch stuff from shared memory by looking up the std::string key value, and write a new record into memory. I'd like to instead be able to keep a reference to the shared memory object around.If I can't directly do that, how would I do it indirectly? I suppose I could keep a non-shared-memory std::vector, and allocate a non-shared memory std::string holding the value of the areaKey, which is a std::string, and then do a cast of the
void*
item back tostd::string
and then use that to fetch a record out of the shared memory area. That all seems like more work than should be strictly necessary for something so elementary. Maybe boost::interprocess::map isn't the right choice for my requirements?
What have I tried? This, which compiles, but I have no idea if I am doing this right. Somehow I feel ugly inside dereferencing an ::iterator
returned from find
, and then immediately taking its address like so:
void ** handle; // actually a parameter in my api.
*handle = (void*)&(*anAreaMap->find(areaKey));
Update The above works. The very sensible advice in the answer below does NOT work however. Using boost::interprocess::string results in complete and total failure and crashes at runtime. Using std::string, which has no right to work unless the authors of Boost coded std::string support in especially, actually works great.