Question

I have leraned the boost sample about "Create vectors in shared_memory". Now My data structure is like :

Data structure:

enum FuncIndex
{
  enmFunc_glBegin,
  ...
}

class CGLParam {};

class Funcall
{
    vector<CGLParam> vecParams;
};

class Global_Funcall
{
    typedef allocator<CGLParam*, managed_shared_memory::segment_manager> ShmemAllocator;
    typedef vector<CGLParam*, ShmemAllocator> MyVector;
    MyVector<FunCall> vecFuncalls;
};


Global_Funcall()
{
    shared_memory_object::remove("MySharedMemory");
    managed_shared_memory segment(create_only, "MySharedMemory", 65536);
    //Initialize shared memory STL-compatible allocator
    const ShmemAllocator alloc_inst(segment.get_segment_manager());

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

void InvokeFuncs(CGLParam *presult)
{
    managed_shared_memory open_segment(open_only,"MySharedMemory");
    listParams = open_segment.find<MyVector>("MyVector").first;

    //      MyVector::const_iterator it;
    //      for (it = listParams->cbegin(); it != listParams->cend(); it++)
    //      {
    //          (*it)->InvokeFunc(presult);
    //      }

}

My problem is "How to construct the vecParams and how to get it". the size of data is very big (opengl function calls) The structure is use to save the opengl function calls.

Was it helpful?

Solution

Besides 'obvious' typos, you try to assign an IPC vector (MyVector*) to a standard vector in the GlobalFuncall constructor. That will never work. C++ is a strongly typed language, so the types have to match if you want to assign[1].

Besides this there seems to be a conceptual problem:

  • if the goal is to have a data collection that could be larger than fits in phyical memory, shared-memory per se isn't going to help. You'd want to look at memory-mapped files
  • if you want shared-memory because you can share it between processes (hence Boost Interprocess), you will need to think of process synchronization, or you will see complicated bugs because of data races.
  • you cannot safely store raw pointers inside this containers. Instead, store the actual elements there (or maybe look at bip::offset_ptr<> if you want to get really fancy).

Here's a 'fixed up' demonstration

  • fixing the C++ compilation issues,
  • changing the element type to be CGLParam instead of CGLParam*
  • fixing the member type to match the SHM vector and
  • adding basic shared mutex synchronization (this is an art in itself and you will want to read more about this)

See it Live On Coliru[1]

#include <vector>

#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/named_recursive_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>

namespace bip = boost::interprocess;
using mutex_type = bip::named_mutex;

class CGLParam {};

typedef bip::allocator<CGLParam, bip::managed_shared_memory::segment_manager> ShmemAllocator;
typedef std::vector<CGLParam, ShmemAllocator> MyVector;

class Funcall
{
    std::vector<CGLParam> vecParams;
};


struct mutex_remove
{
    mutex_remove() { mutex_type::remove("2faa9c3f-4cc0-49c5-8f79-f99ce5a5d526"); }
    ~mutex_remove(){ mutex_type::remove("2faa9c3f-4cc0-49c5-8f79-f99ce5a5d526"); }
} remover;

static mutex_type mutex(bip::open_or_create,"2faa9c3f-4cc0-49c5-8f79-f99ce5a5d526");

class Global_Funcall
{
    MyVector* vecFuncalls;
    Global_Funcall()
    {
        bip::scoped_lock<mutex_type> lock(mutex);

        bip::shared_memory_object::remove("MySharedMemory");
        bip::managed_shared_memory segment(bip::create_only, "MySharedMemory", 65536);
        //Initialize shared memory STL-compatible allocator
        const ShmemAllocator alloc_inst(segment.get_segment_manager());

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

};

void InvokeFuncs(CGLParam *presult)
{
    bip::scoped_lock<mutex_type> lock(mutex);
    bip::managed_shared_memory open_segment(bip::open_only, "MySharedMemory");
    auto listParams = open_segment.find<MyVector>("MyVector").first;

    MyVector::const_iterator it;
    for (it = listParams->cbegin(); it != listParams->cend(); it++)
    {
        //it->InvokeFunc(presult);
    }

}

int main()
{
}

[1] Unless, of course, there's a suitable conversion

[2] Coliru doesn't support the required IPC mechanisms :/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top