2

I want to quickly pass an object containing a vector of pointers to another process. This is what I'm trying to send:

typedef std::vector<Shelve*> ShelveVec;

This is what I've tried:

managed_shared_memory segment{create_only, "HwDescriptionObjects", 1056};

BeBoardInterface *sBeBoardInterface = segment.construct<BeBoardInterface>("BeBoardInterface")(fBeBoardFWMap);
CbcInterface *sCbcInterface = segment.construct<CbcInterface>("CbcInterface")(fBeBoardFWMap);
ShelveVec *sShelveVector = segment.construct<ShelveVec>("ShelveVector")(fShelveVector, alloc_inst);

qDebug() << "Size " << sShelveVector->size();

The first two shared memory objects work but I've tried the vector which I understand from reading the BOOST documentation is a little trickier to implement due to things like the begin pointer allocation. When accessed from the process, it ends up being empty.

Is this possible to do or not?

EDIT, As much info as I can give:

I do a series of loops to initialise these classes:

uint32_t cNShelve = 0
for(auto &kv : mapSettings.keys())
{
    cShelveId=kv;
    fShelveVector.push_back(new Shelve(cShelveId));
    for(auto &kv_ : mapSettings.value(kv).keys()):
    {
        cBeId = kv_;
        BeBoard* cBeBoard = new BeBoard(cShelveId, cBeId);
        fShelveVector.at(cNShelve)->addBoard(cBeBoard);
    }
cNShelve++;
}

Edit2: A cheap solution:

managed_shared_memory segment{create_only, "HwDescriptionObjects", 1056};
uint32_t cNShelve = 0
for(auto &kv : mapSettings.keys())
{
    cShelveId=kv;
    Shelve *sShelve = segment.construct<Shelve>("Shelve")(cShelveId)
    fShelveVector->push_back(sShelve);
    for(auto &kv_ : mapSettings.value(kv).keys()):
    {
        cBeId = kv_;
        BeBoard* cBeBoard = segment.construct<BeBoard>("BeBoard")(cShelveId, cBeId);
        fShelveVector.at(cNShelve)->addBoard(cBeBoard);
    }
cNShelve++;
}

Contents of the HwDescription Objects

fiz
  • 906
  • 3
  • 14
  • 38
  • I've added a smaller version – fiz Feb 12 '15 at 10:49
  • 1
    I've updated my answer. Couldn't really get into a demo because of the missing type definitions. I understand you can't share. I hope you find the links useful – sehe Feb 12 '15 at 10:56
  • Essentially I have something which creates all these objects and I wish other processes to use these objects separately without having to reinitialise them. I have two paths as far as I can see - socket serialisation/deserialisation or shared memory. Do you think this is a sensible path? – fiz Feb 12 '15 at 12:17
  • 1
    Depends on the usage patterns. I think `construct<>` ing each and every object might incur a huge overhead (see eg. [bad_alloc is thrown](http://stackoverflow.com/questions/21287171/bad-alloc-is-thrown/21287572#21287572)) and [How do I measure the size of a boost interprocess vector in shared memory?](http://stackoverflow.com/q/26305868/85371)). So yes, for many small objects - that you don't want to/can make allocator-aware - I'd suggest serialization – sehe Feb 12 '15 at 12:21

1 Answers1

2

You can.

However you have to make sure the pointers are also allocated from the shared memory.

If you show a SSCCE I'll show you how I'd do that.


Update

After looking at at the updated question I must say it's gonna be involved. You need to allocate Shelves from shared memory, and the same for all it's guts[1] (like the BeBoards) that are now being allocated from the heap.

Suggestions:

  1. If really you just need the pointer as identification, don't worry
  2. Perhaps you can share just the vector indices (in case they're meaningful in other process spaces)
  3. If you made the classes allocator-aware you could use boost::container::scoped_allocator_adaptor to ease the pain a little.

    I've created demos using scoped allocators (from Boost) in the following answers:


[1] (technically, at least the parts you're accessing from across process boundaries)

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • So what you're saying is, say if I initialise an object into shared memory and add these to a vector it may not actually work? If there are any pointers initialised inside the objects - say for example BeBoard initialises an object inside itself - that too will need to be stored in shared memory? As far as I am aware, I think these objects actually only contain PODs - just maps and possibly vectors of chars and strings - with no pointers initialised inside. I've added an attempt at an answer and included the code I'm using. – fiz Feb 12 '15 at 12:14
  • 1
    The simple guideline is, you cannot _use_ a raw pointer from a different process space inside your process. All the constraints/loop-holes logically follow from there. It doesn't matter when things are POD - not when pointers are involved (pointers -are- POD, but they're not valid for indirection in the other process) – sehe Feb 12 '15 at 12:18
  • Thankyou for your very informative answers. If I could more than 1up upi, I would =D – fiz Feb 12 '15 at 12:36