El truco consiste simplemente en redefinir el operador “new” para la clase de los objetos que queremos compartir:
extern "C++" { using namespace std; namespace avelino { class TShared { private: int a; public: TShared(); void setA(int v); int getA(); static void *memArea; void *operator new (unsigned int size); }; } } ... void *TShared::operator new (unsigned int size) { return TShared::memArea; }
Como se puede observar, hacemos que
new TShared()
devuelva un puntero a un área de memoria controlada por nosotros (no estoy implementando el delete
ni estoy realizando una gestión de memoria como tal: obsérvese que dos new TShared()
seguidos devolverían la misma posición de memoria, estoy haciéndolo así para facilitar la comprensión).Bueno, ya tenemos una clase que, al hacerle
new
nos va a devolver un puntero a una dirección de memoria controlada por nosotros. Ahora sólo nos queda inicializar dicho puntero adecuadamente.Debe haber un proceso que cree el objeto en memoria compartida:
int shmid = shmget(SHM_KEY, sizeof(TShared), IPC_CREAT | IPC_EXCL | 0700); TShared::memArea = shmat(shmid, NULL, 0); TShared *p = new TShared(); p->setA(12345);
Como se puede ver, antes de hacer el
new TShared()
inicializo TShared::memArea
con la zona de memoria compartida que acabo de crear (he omitido, por claridad, los if
que controlan los posibles errores que puedan devolver la funciones shmget
, shmat
, etc.). Ahora nuestro objeto de tipo TShared
está en la memoria compartida identificada por SHM_KEY
(una constante cualquiera definida por nosotros y mayor que cero).Si otro proceso quiere acceder a dicho “objeto compartido” sólo tendrá que acceder a dicha memoria compartida y hacer el cast correspondiente:
int shmid = shmget(SHM_KEY, sizeof(TShared), 0700); TShared::memArea = shmat(shmid, NULL, 0); TShared *p = (TShared *) TShared::memArea; cout << "a = " << p->getA() << endl;
El código fuente completo lo he puesto en la sección soft de la web.
Si, claro, se podría (y se debería) encapsular. Con respecto a los posibles errores que devuelva shmget y shmat, para eso están las excepciones como bien dices. Gracias por comentar :-).
Muy didáctico.
Supongo que se podría encapusular la reserva de memoria compartida dentro del constructor, que incluso podría el tener SHM_KEY como argumento. ¿O hay alguna limitación que obligue a hacerlo desde fuera y previamente? Eso sí, se perderían los códigos de error devueltos por shget, shmat, etc (habría que usar excepciones).
Lo sentimos. No se permiten nuevos comentarios después de 90 días.