poukill poukill - 3 years ago 70
C++ Question

Boost.interprocess Vector as class member

I would like to place a struct in a shared memory using Boost.Interprocess. This struct will be shared between two processes as a main exchange zone for serialized data. I am currently searching for the best solution in term of simplicity.

namespace bi = boost::interprocess;

typedef bi::allocator<SimpleData, bi::managed_shared_memory::segment_manager> ShmemSimpleDataAllocator;
typedef bi::vector<SimpleData, ShmemSimpleDataAllocator> SimpleDataVector;

struct SimpleData
{
SimpleData() {}
SimpleData(char* ptr)
:data(ptr)
{}

/** Offset pointer to the data */
bi::offset_ptr<char> data;
};

// Main shared structure
struct SharedMainStruct // EDITED, thanks Sehe
{
SharedMainStruct(ShmemSimpleDataAllocator simple_allocator)
:m_inputs(simple_allocator),
m_outputs(simple_allocator)
{}

// Inputs, outputs and properties
SimpleDataVector m_inputs;
SimpleDataVector m_outputs;

bi::interprocess_mutex m_mutex;
bi::interprocess_condition m_cond;
};

// Main code here
// Create managed shared memory
my_sho= new bi::managed_shared_memory (bi::create_only, "test_SO", 1000000);

// Build main structure in shared memory
ShmemSimpleDataAllocator data_allocator(my_sho->get_segment_manager());
m_main_struct = my_sho->construct<SharedMainStruct>("main")(data_allocator); // (1)


The idea is to place this
SharedMainStruct
in shared memory so that it is accessible for both processes. Is this code line (1) correct ? I would guess that I miss some runtime code like in the documentation right ? Like :

//Initialize shared memory STL-compatible allocator
const ShmemSimpleDataAllocatoralloc_inst (segment.get_segment_manager());

//Construct a vector named "MyVector" in shared memory with argument alloc_inst
SimpleDataVector* myvector = segment.construct<SimpleDataVector>("SimpleDataVector")(alloc_inst);


-- UPDATED --
Yes, Vectors can be stored as member variables. We should provide allocators as parameters...

Answer Source

The essence:

Classes are laid out contiguously in memory, so you cannot literally store some parts of it selectively in shared memory.

For the same reason, storing offset_ptr outside shared-memory is useless, and you can simply replace it by a raw pointer.

Further brainstorming

The previous two sentences should be enough to clear up any confusion.

You /can/ of course store the MainStruct in shared memory. This could help iff all data in the MainStruct can be shared.

If you need so share just that part of MainStruct, it seems obvious to make that explicit:

// Inputs, outputs and properties
struct SharedBuffers {
     template <typename Alloc> 
     SharedBuffers(Alloc alloc = {}) : m_inputs(alloc), m_outputs(alloc) {}

     Shared::Vector<SimpleData> m_inputs;
     Shared::Vector<SimpleData> m_outputs;
};

SharedBuffers* m_buffers; // bip::offset_ptr<> is overkill outside shared memory

Mild suggestion to replace the 'raw' offset_ptr` with a shared vector of char instead.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download