2012-08-31 22 views
13

He el siguiente patrón de código:Cómo almacenar objetos stl en la memoria compartida (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; 
    ... 
}; 

Ahora quiero para almacenar un objeto de tipo C en una memoria compartida, por lo que los diferentes procesos pueden añadir, actualizar y leerlo. ¿Cómo puedo hacer esto? (Nota: Yo sé cómo almacenar un simple matriz C que tiene un tamaño fijo en la memoria compartida Además, recuerde que B.table puede tener entradas arbitrarias

+1

Esto no es fácil. Necesitará un asignador especial para todos sus contenedores que sepa sobre la memoria compartida. En C++ 11 esto es un poco más fácil de implementar gracias a los asignadores con estado, pero no es trivial en ningún caso. –

+1

¿Qué plataforma? – tenfour

+0

Esto depende de la plataforma. – someguy

Respuesta

17

Uso boost::interprocess, esta biblioteca expone esta función

... EDIT: Aquí hay algunos cambios que necesita hacer:.

el ejemplo ya define un asignador que asignar del segmento de memoria compartida, se necesita pasar esto a la map y la queue esto significa que tendrá para cambiar sus definiciones:

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

Para queue, esto es un poco complicado, debido al hecho de que en realidad es sólo un adaptador, por lo que necesita para pasar en la clase de implementación real como un parámetro de plantilla:

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

ahora su clase C cambia ligeramente :

class C 
{ 
    B entries; 
    QueueType d, e; 

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

Ahora desde el gestor de segmento, construir una instancia de C con el asignador.

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

Creo que debería hacer el truco. NOTA: Necesitará proporcionar dos asignadores (uno para queue y otro para map), sin estar seguro si puede construir dos asignadores desde el mismo administrador de segmentos, pero no veo por qué no.

+0

Lo miré antes. Nunca lo había usado antes, así que estaba un poco indeciso. ¿Puede darme una idea aproximada de cómo tendría que adaptar el código en el siguiente enlace para cumplir con mis requisitos? http://www.boost.org/doc/libs/1_37_0/doc/html/interprocess/quick_guide.html#interprocess.quick_guide.qg_interprocess_map – shobhu

+0

@shobhu, actualizado con algunos cambios al ejemplo que debería funcionar ... – Nim

2

Esto puede ser complicado. Para empezar, necesitará un asignador personalizado: Boost Interprocess tiene uno, y yo comenzaría con él. En su ejemplo exacto, esto puede ser suficiente, pero más generalmente, deberá asegurarse de que todos los subtipos también usen la memoria compartida. Por lo tanto, si desea mapear desde una cadena, esa cadena también necesitará un asignador personalizado, lo que significa que tiene un tipo diferente de std::string, y no puede copiar o asignarlo desde std::string (pero usted puede utilizar los dos iterador constructor, por ejemplo:

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

con accesos como:

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

Y, por supuesto, cualquier tipo se definen los que van en el mapa también debe utilizar memoria compartida para cualquier asignación s: Boost Interprocess tiene un offset_ptr que puede ayudar aquí.

1

La creación y el uso de objetos STL en la memoria compartida no es complicado todavía (especialmente al utilizar las envolturas boost :: interprocess). Seguro también deberías usar mecanismos de sincronización (tampoco es un problema con el named_mutex de boost).

El verdadero desafío es mantener la consistencia de los objetos STL en una memoria compartida. Básicamente, si uno de los procesos se estrella en un mal momento en el tiempo, deja otros procesos con dos grandes problemas:

  • un mutex bloqueado (se puede resolver utilizando asignaciones difíciles-PID-a mutex, exclusiones mutuas robustos (donde esté disponible), mutexes temporizados, etc.

  • Objeto STL en el estado incoherente (por ejemplo, estructura de mapa semi-actualizada durante el procedimiento de borrado). En general, esto no es recuperable aún, necesita destruir y volver -construye un objeto en una región de memoria compartida desde cero (probablemente matando a todos los demás procesos). Puedes intentar interceptar todas las señales externas posibles en tu aplicación y cruzar los dedos para que todo salga bien y procesar s nunca falla en un mal momento.

Solo téngalo en cuenta cuando decida utilizar memoria compartida en su sistema.

Cuestiones relacionadas