2012-08-31 59 views
13

私は、次のコードパターンました:共有メモリ(C++)にstlオブジェクトを格納する方法は?

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は任意のエントリを有することができることを覚えて使用boost::interprocessは、このライブラリは、この機能を公開

+1

これは簡単ではありません。共有メモリを知っているすべてのコンテナに特別なアロケータが必要です。 C++ 11では、ステートフルなアロケータのおかげでやや簡単に実装することができますが、どのような場合でもそれほど重要ではありません。 –

+1

どのプラットフォームですか? – tenfour

+0

これはプラットフォームに依存します。 – someguy

答えて

17

。。。編集:ここにいくつかの変更が必要です:

この例では共有メモリブロックから割り当てられるアロケータが既に定義されていますので、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) 
    { } 
} 
については

、これは、テンプレートパラメータとして、実際の実装クラスに合格する必要があるので、それは、本当にただのアダプタだという事実を、少し複雑です:今

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); 

私はそのトリックを行うべきだと思います。注:同じセグメントマネージャーから2つのアロケーターを構築できるかどうかはわかりませんが、2つのアロケーター(queueに1つ、mapに1つ)を用意する必要があります。

+0

私はそれを前に見ました。私はこれまでにそれを使用したことがないので、少し躊躇した。私の要件を満たすために、以下のリンクにコードをどのように適用しなければならないかについて、大まかに考えてください。 http://www.boost.org/doc/libs/1_37_0/doc/html/interprocess/quick_guide.html#interprocess.quick_guide.qg_interprocess_map – shobhu

+0

@ shobhu、動作すべき例のいくつかの変更で更新されました... – Nim

2

これは扱いにくいことがあります。まず、カスタムアロケータが必要です。Boost プロセスには1つしかありません。正確な例では、 で十分ですが、より一般的には、 すべてのサブタイプも共有メモリを使用する必要があります。したがって、 から文字列をマップする場合は、その文字列にはstd::string以外のタイプのカスタムアロケータ( )が必要です。 をstd::stringからコピーすることはできませんまた、任意の割り当てのために 共有メモリを使用しなければならないマップに入り、ユーザーが定義し

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

そしてもちろんの

、任意の種類:のようなアクセスを

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

:2つのイテレータ コンストラクタ、例えばを使用することができますs:Boost Interprocessには offset_ptrがあります。

1

STLオブジェクトを共有メモリにビルドして使用するのは難しくありません(特にboost :: interprocessラッパーを使用する)。確かに、同期メカニズムも使うべきです(boostのnamed_mutexには問題ありません)。

本当の挑戦は、STLオブジェクトの一貫性を共有メモリに保持することです。プロセスの一つが時間内に悪い点でクラッシュした場合、基本的に、それは二つの大きな問題に他のプロセスを残します:

  • Aがミューテックスをロックし(トリッキーPIDツーミューテックスマッピング、堅牢なミューテックスを使用して解決することができます(可能であれば)、タイミングミューテックスなど

  • 矛盾した状態のSTLオブジェクト(たとえば、erase()プロシージャ中の半更新マップ構造)一般に、これはまだ回復できません。共有メモリ領域内のオブジェクトを最初から作成する(他のすべてのプロセスも同様に終了する可能性がある)。アプリ内の可能なすべての外部信号を傍受し、悪い瞬間に決して失敗することはありません。

システムで共有メモリを使用することを決定するときは、この点に留意してください。

関連する問題