2012-08-31 20 views
13

mam następujący wzór kodu:Jak przechowywać obiekty STL we wspólnej pamięci (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; 
    ... 
}; 

teraz chcę przechowywać obiekt typu C w pamięci współdzielonej, tak, że różne procesy mogą dołączyć, aktualizacja i przeczytać. Jak mogę to zrobić? (Uwaga: wiem, jak przechowywać prostą tablicę C, który ma stały rozmiar w pamięci współdzielonej również pamiętać, że B.table mogą mieć dowolne wpisy

+1

To nie jest łatwe. Potrzebowałbyś specjalnego przydziału dla wszystkich swoich kontenerów, które wiedzą o pamięci współdzielonej. W C++ 11 jest to nieco łatwiejsze do wdrożenia dzięki stanowym alokatorom, ale w żadnym wypadku nie jest to banalne. –

+1

Która platforma? – tenfour

+0

To zależy od platformy. – someguy

Odpowiedz

17

Zastosowanie boost::interprocess, biblioteka ta naraża tę funkcjonalność

... EDYCJA: Oto kilka zmian, które musisz wykonać:

Przykład już określa alokator, który będzie alokował z bloku pamięci współdzielonej, musisz przekazać to do map i queue. Oznacza to, że będziesz mieć aby zmienić swoje definicje:

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) 
    { } 
} 

Dla queue, jest to nieco skomplikowane, ze względu na fakt, że jest to naprawdę tylko adapter, więc trzeba przejść w realnym klasie wdrożenia jako parametr szablonu:

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

Teraz twoja klasa C zmiany nieznacznie :

class C 
{ 
    B entries; 
    QueueType d, e; 

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

teraz od kierownika segmentu, konstruować wystąpienie C z podzielnika.

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

Myślę, że powinienem załatwić sprawę. UWAGA: Musisz podać dwa podzielniki (jeden dla queue i jeden dla map), nie wiesz, czy możesz zbudować dwa podzielniki z tego samego menedżera segmentów, ale nie widzę powodu, dlaczego nie.

+0

Spojrzałem na to wcześniej. Nigdy wcześniej tego nie używałem, więc trochę się wahałem. Czy możesz podać mi przybliżony pomysł, w jaki sposób będę musiał dostosować kod pod poniższym linkiem, aby spełnić moje wymagania. http://www.boost.org/doc/libs/1_37_0/doc/html/interprocess/quick_guide.html#interprocess.quick_guide.qg_interprocess_map – shobhu

+0

@shobhu, zaktualizowany pewnymi zmianami w przykładzie, który powinien zadziałać ... – Nim

2

Może to być trudne. Na początek potrzebujesz niestandardowego przydziału: Zwiększ Interprocess ma jeden i zacznę od niego. W twoim dokładnym przykładzie, może to być wystarczające, ale bardziej ogólnie, musisz upewnić się, że wszystkie podtypy również korzystają z pamięci współdzielonej. Dlatego jeśli chcesz zmapować z ciąg znaków, ten ciąg będzie również wymagał niestandardowego przydziału, co oznacza, że ​​ ma inny typ niż std::string i nie można go skopiować z przypisanego do niego z std::string (ale można użyć dwóch iterator konstruktora, np

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

z dostępów jak:

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

i oczywiście wszelkiego rodzaju można zdefiniować, które idą do mapy należy również użyć pamięci współdzielonej do przydziału s: Boost Interprocess ma offset_ptr, które mogą pomóc tutaj.

1

Budowanie i używanie obiektów STL w pamięci współdzielonej nie jest jeszcze trudne (zwłaszcza przy użyciu owijania :: interprocessy). Na pewno powinieneś także użyć mechanizmów synchronizacji (także nie jest to problem z boostem o nazwie named_mutex).

Prawdziwym wyzwaniem jest zachowanie spójności obiektów STL we wspólnej pamięci. Zasadniczo, jeśli jeden z procesów awarii w złym momencie, pozostawia inne procesy z dwoma dużymi problemami:

  • Zablokowany mutex (może być rozwiązany za pomocą skomplikowanych PID-to-mutex mapowania, solidne muteksy (gdziekolwiek dostępne), muteksy czasowe itp.

  • Obiekt STL w niespójnym stanie (np. częściowo zaktualizowana struktura mapy podczas procedury kasowania()). Zasadniczo nie można tego jeszcze naprawić, musisz zniszczyć i ponownie -konstruuj obiekt w regionie pamięci współdzielonej od podstaw (prawdopodobnie zabijając również wszystkie inne procesy). Możesz spróbować przechwycić wszystkie możliwe sygnały zewnętrzne w swojej aplikacji, a palce skrzyżowane mają nadzieję, że wszystko pójdzie dobrze i proces Nigdy nie zawieść w złym momencie.

Należy o tym pamiętać, decydując się na korzystanie z pamięci współdzielonej w systemie.

Powiązane problemy