La adición de un asignador de una plantilla de clase C ++ para la creación de objetos de memoria compartida

StackOverflow https://stackoverflow.com/questions/2423270

  •  19-09-2019
  •  | 
  •  

Pregunta

En resumen, mi pregunta es: Si tiene clase, MyClass<T>, ¿cómo se puede cambiar la definición de clase para apoyar los casos donde se tiene MyClass<T, Alloc>, similar a la forma, por ejemplo, el vector STL proporciona.

Necesito esta funcionalidad para soportar un asignador de memoria compartida. En concreto, estoy tratando de implementar una memoria cíclica en la memoria compartida. Actualmente, cuenta con la siguiente ctor:

template<typename ItemType>
SharedMemoryBuffer<ItemType>::SharedMemoryBuffer( unsigned long capacity, std::string name )

donde ItemType es el tipo de los datos a ser colocado en cada ranura de la memoria intermedia.

Ahora, esto funciona espléndida cuando se crea la memoria intermedia del programa principal de este modo

SharedMemoryBuffer<int>* sb;
sb = new SharedMemoryBuffer<int>(BUFFER_CAPACITY + 1, sharedMemoryName);

Sin embargo, en este caso el búfer en sí no se crea en la memoria compartida y por lo tanto no es accesible para otros procesos. Lo que quiero hacer es ser capaz de hacer algo como

typedef allocator<int, managed_shared_memory::segment_manager>  ShmemAllocator;
typedef SharedMemoryBuffer<int, ShmemAllocator> MyBuffer;

managed_shared_memory segment(create_only, "MySharedMemory", 65536);
const ShmemAllocator alloc_inst (segment.get_segment_manager());
MyBuffer *mybuf = segment.construct<MyBuffer>("MyBuffer")(alloc_inst);

Sin embargo, no sé cómo hacer para añadir un asignador explícita a la plantilla de clase.

¿Fue útil?

Solución

lo que me hace confundir es decir, ¿por qué es necesario asignar o crear un objeto en SharedMemory (SHM), por ejemplo, si se reserva la memoria compartida del tamaño de 65536 Bytes, a continuación, supongamos que consigue su memoria compartida en la dirección 0x1ABC0000, si la reserva el éxito que tendrá el espacio de memoria libre y directamente accesible en 0x1ABC0000 to 0x1ABCFFFF.

A continuación, cuando su aplicación necesidad de "asignar" objeto en SHM del tamaño sizeof(SHMObject), y el gestor de la memoria ver que la dirección en 0x1ABC0000+0x1A está libre, el administrador de memoria solo debe devolver el valor 0x1ABC001A, y marcar ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) ) estaba ocupado, y sólo tiene a emitir: SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);

y por supuesto que está suponiendo que tiene su propio gestor de memoria a medida que el trabajo en determinado rango de direcciones de memoria.

En cuanto a la plantilla, yo realmente no entiendo cómo se ve su memoria cíclica como SHM, pero he hecho que antes de usar SHM, mi aplicación es la siguiente: `

//memory SHM allocator
template<typename T> class ShmRingAllocator
{
    protected:
        void* baseAddress;
    public:
        ShmRingAllocator(void* baseAddress,int memSize);
        void* allocate(); //this function do what I described earlier, or you can use placement new: new (baseAddress+offset)T;
}

//some kind of shared_ptr<> that handle object in SHM, this provides mechanishm to check is the pointer still valid in shm or not
template<typname T> ShmRingObjectPtr 
{
    protected:
         T* object; //mapped address of object at current process
         ShmBuffer* shm; //every object has pointer to which SHM does this pointer pointing at
    public:
         virtual T* operator->(); //operator overload to access T object
}

class ShmBuffer //base class for all kind of SHM buffer
{
    protected:
         std::string shmName;
         void* shmBasePtr;
}

template<typename T,class A=ShmRingAllocator<T>> ShmRingBuffer : public ShmBuffer
{
    protected:
         A allocator;
    public:
         ShmRingObjectPtr<T> insert() //push one element to ring buffer
         {
              return ShmRingObjectPtr<T>((T*)this->allocator.allocate(),this);
         }
}

`

Otros consejos

Creo que usted está buscando para el estándar colocación de nuevo .

Si shm_addr es un puntero a la memoria compartida void* que puede hacer:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

y el nuevo MyBuffer se construirá en el lugar determinado. Esto puede funcionar con cualquier tipo de objeto, incluyendo tipos con plantilla.

Usted puede envolver esto en una función separada si lo considera oportuno.

Para destruir algo creado con la colocación estándar nueva que necesita llamar explícitamente al destructor. Esto se debe a delete trataría de desasignar la memoria como new memoria asignada regular que no sería una cosa válida a hacer. Esta es la única vez en C ++ que es necesario llamar a un destructor de forma explícita.

pBuf->~MyBuffer();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top