2012-08-31 135 views
13

我已經下面的代碼圖案:如何將stl對象存儲在共享內存(C++)中?

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可以有任意條目

+1

這並不容易。對於知道共享內存的所有容器,您都需要一個特殊的分配器。在C++ 11中,由於有狀態的分配器,實現起來要容易一些,但在任何情況下都不是微不足道的。 –

+1

哪個平臺? – tenfour

+0

這是平臺相關的。 – someguy

回答

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),不確定您是否可以從同一個段管理器構造兩個分配器,但我不明白爲什麼不。

+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 進程之間有一個,我會先從它開始。在你確切的例子中,這可能是足夠的,但更一般地說,你需要確保所有的子類型都使用共享內存。因此,如果要從 映射一個字符串,該字符串還需要一個自定義分配器,這意味着 它具有與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())] ... 

和當然,任何類型,定義要進入地圖也必須使用 共享內存的所有分配s:Boost Interprocess有一個 offset_ptr這可能對此有所幫助。

1

在共享內存中構建和使用STL對象並不麻煩(特別是使用boost :: interprocess包裝器)。當然,你也應該使用同步機制(對boost的named_mutex也不是問題)。

真正的挑戰是保持共享內存中STL對象的一致性。基本上,如果其中一個進程在時間上的壞點崩潰,它的葉子其他進程有兩個大問題:

  • 鎖定的互斥體(可以使用棘手的PID至互斥的映射,健壯的互斥鎖解決(任何可用的地方),定時互斥鎖等。

  • STL對象處於不一致狀態(例如擦除()過程中的半更新映射結構)。一般來說,這是不可恢復的,你需要銷燬和重新 - 從頭開始​​構建共享內存區域中的對象(也可能會終止所有其他進程)。您可能會嘗試攔截應用中的所有可能的外部信號,並跨越手指,希望一切都會順利進行並處理在一個不好的時刻永遠不會失敗。

當決定在您的系統中使用共享內存時,請記住這一點。