如何在共享内存(C ++)中存储stl对象?

时间:2012-08-31 07:17:07

标签: c++ stl shared-memory

我有以下代码模式:

class A {
    double a, b, c;
    ...
};

class B {
    map<int, A> table; // Can have maximum of MAX_ROWS elements.
    ...
};

class C {
    B entries;
    queue<int> d;
    queue<int> e;
    ...
};

现在我想在共享内存中存储C类型的对象,以便不同的进程可以追加,更新和读取它。我怎样才能做到这一点? (注意:我知道如何在共享内存中存储一​​个固定大小的简单C数组。另外,请记住B.table可能有任意条目。

3 个答案:

答案 0 :(得分:17)

使用boost::interprocess,此库会公开此功能。

编辑:以下是您需要做的一些更改:

该示例已经定义了将从共享内存块分配的分配器,您需要将其传递给mapqueue。这意味着您必须更改定义:

class B
{
  map<int, A, less<int>, MapShmemAllocator> table;

  // Constructor of the map needs the instance of the allocator
  B(MapShmemAllocator& alloc) : table(less<int>(), alloc)
  { }
}

对于queue,这有点复杂,因为它实际上只是一个适配器,因此您需要将实际的实现类作为模板参数传递:

typedef queue<int, deque<int, QueueShmemAllocator> > QueueType;

现在,您的班级C略有变化:

class C
{
  B entries;
  QueueType d, e;

  C(MapShmemAllocator& allocM, QueueShmemAllocator& allocQ) : entries(allocM), d(allocQ), e(allocQ)
  { }
}

现在,从分部管理器,使用分配器构建C的实例。

C *pC = segment.construct<C>("CInst")(allocM_inst, allocQ_inst); 

我认为应该这样做。注意:您需要提供两个分配器(一个用于queue,一个用于map),不确定是否可以从同一个段管理器构造两个分配器,但我不明白为什么不这样做。

答案 1 :(得分:3)

这可能很棘手。首先,你需要一个自定义分配器:Boost Interprocess有一个,我从它开始。在你的确切例子中, 这可能就足够了,但更一般地说,你需要确保这一点 所有子类型也使用共享内存。因此,如果你想要映射 一个字符串,该字符串也需要一个自定义分配器,这意味着 它的类型与std::string不同,你不能复制或 从std::string分配给它(但你可以使用两个迭代器 构造函数,例如:

typedef std::basic_string<char, std::char_traits<char>, ShmemAllocator> ShmemString;
std::map<ShmemString, X, std::less<ShmemString>, ShmemAllocator> shmemMap;

访问次数如下:

shmemMap[ShmemString(key.begin(), key.end())] ...

当然,您定义的任何进入地图的类型也必须使用 任何分配的共享内存:Boost Interprocess有一个 offset_ptr这可能对此有所帮助。

答案 2 :(得分:2)

在共享内存中构建和使用STL对象并不棘手(特别是使用boost :: interprocess包装器)。当然,你也应该使用同步机制(也不是boost&named #mutex的问题)。

真正的挑战是保持STL对象在共享内存中的一致性。基本上,如果其中一个进程在一个不好的时间点崩溃,它会让其他进程出现两个大问题:

  • 锁定的互斥锁(可以使用棘手的PID到互斥映射,强大的互斥锁(在任何可用的地方),定时的互斥锁等来解析。

  • 处于不一致状态的STL对象(例如,擦除()过程中的半更新地图结构)。通常,这是不可恢复的,您需要从头开始在共享内存区域中销毁和重构对象(可能也会杀死所有其他进程)。您可以尝试拦截应用程序中的所有可能的外部信号,并且交叉手指希望一切顺利,并且过程永远不会在糟糕的时刻失败。

在决定在系统中使用共享内存时,请记住这一点。