I'm right now getting into shared memory using boost::interprocess
.
I've defined a few std::unordered_map
and std::unordered_set
types like in the following manner:
#include <boost/interprocess/allocators/allocator.hpp>
#include <unordered_map> // NOT the boost implementation ...
...
namespace ipc = boost::interprocess;
/**
* allocator type needed to construct maps in shared memory
*/
typedef ipc::allocator<std::pair<const size_t, std::string>,
ipc::managed_shared_memory::segment_manager> OBJ_MAP_ALLOCATOR;
/**
* map type to construct maps in shared memory
*/
typedef std::unordered_map<size_t,
std::string,
std::hash<size_t>,
std::equal_to<size_t>,
OBJ_MAP_ALLOCATOR> OBJ_MAP_TYPE;
I initialised them like this:
ipc::managed_shared_memory segment;
// allocate segment etc ...
OBJ_MAP_ALLOCATOR alloc_inst(segment.get_segment_manager());
objMap = segment.find_or_construct<OBJ_MAP_TYPE> (ipc::unique_instance)(alloc_inst);
This seems to work fine, i haven't found any problems during compile- or runtime (working on macOS, Apple LLVM version 9.1.0 (clang-902.0.39.1)
, with C++14 standard).
In the Boost documentation, only the Boost containers, or the interprocess-specific implementations are mentioned. Unfortunately, they do not seem to contain the unordered versions.
So, i wonder if there's anything problematic about using the default STL containers with the Boost allocators ? Maybe on a different platform ?
Any hint appreciated !
Update:
I was wondering if it was working in a different environment, so i wrote a minimal example on Coliru (which surprisingly works with std::string
):
unordered_map
will cope with Boost Interprocess allocators IFF your library implementation has support for stateful allocators¹ and allocators using non-raw pointer types.Even so, like @rustyx mentions, you're going to be in deep trouble if you actually share the memory with another process. The other process is likely to map the segment at a different base address, making all pointers stored inside the memory region invalid.
Here's what I usually prefer to write:
Notable details:
This bit:
is a convenient short-cut for doing:
This works because the implicit conversion from segment-manager pointer to allocator instance is allowed.
Enter MAGIC
You'll note that the nested allocator is clumsy to work with:
That's what the designers of
scoped_allocator_adaptor
tried to solve. If you change the allocator into:You can suddenly just write:
This is because in-place construction is defined in terms of uses- allocator construction (see [allocator.uses.construction])
See it Live On Coliru
¹ prepare to be surprised, @SergeyA. Libstdc++ didn't support this last time I checked, but its
unordered_map
supports it since GCC 4.9.0, and OP seems to have anecdotal evidence that libc++ does (although we don't even know whether there was ever an instance of the typedef :))