I\'m using boost::interprocess to share objects between processes. I have two files, a \"server.cpp\" that generates a struct object and passes the object into a map with an
Like Justin mentioned, std::string
is itself a container that dynamically allocates.
Just using Interprocess's string
is not enough. In fact, that's just boost::container::basic_string<>
really.
The important thing is using the allocator.
However, using a map with an allocator, and passing the allocator whenever you need to construct the contained containers (ad nauseam) is annoying.
These make it so that you don't have to know the allocator, any container that knows how to use scoped allocators will pass the allocator onto the nested container.
Live On Coliru ¹
#include
#include
#include
#include
#include
#include
#include
namespace bip = boost::interprocess;
namespace Shared {
using Segment = bip::managed_shared_memory;
using Manager = Segment::segment_manager;
template using Alloc
= boost::container::scoped_allocator_adaptor >;
using String = bip::basic_string, Alloc >;
template > using Map
= bip::map > >;
struct Order {
using allocator_type = Alloc;
template
Order(int i, S const& s, Alloc alloc = {}) : i(i), s(s, alloc) {}
int i;
String s;
};
}
int main() {
try {
using namespace Shared;
Segment segment(bip::open_or_create, "095540a3-ceaa-4431-828d-df21d5e384ae", 65536);
auto& pmap = *segment.find_or_construct
I notice that the map is Map
: the key seems to duplicate the integer value inside Order
.
Map
You could either make it Map
and get a much more streamlined experience (because there's no need for std::piecewise_construct
):
Live On Coliru
auto& pmap = *segment.find_or_construct
Alternatively, you should consider using Multi-Index which is able to index Order
directly by a member of the type:
Live On Coliru
namespace bmi = boost::multi_index;
using Table = bmi::multi_index_container >
>,
Alloc
>;
Sadly, Multi Index doesn't quite play as well with nested types using allocators, so you'll have to pass it along again:
if (pmap.empty()) {
std::cout << "Inserting data\n";
pmap.emplace(1, "one", pmap.get_allocator());
pmap.emplace(2, "two", pmap.get_allocator());
pmap.emplace(3, "three", pmap.get_allocator());
} else {
std::cout << "Existing data:\n";
for (Order const& o : pmap) {
std::cout << o.i << " " << o.s << "\n";
}
// demonstrate lookup:
std::cout << "Finding element 2:" << pmap.find(2)->s << "\n";
}
Prints
Existing data:
1 one
2 two
3 three
Finding element 2:two
¹ using mapped files on Coliru instead. The refactored code makes this a 1-line change.