Adicionando um alocador a um modelo de classe C ++ para criação de objetos de memória compartilhada

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

  •  19-09-2019
  •  | 
  •  

Pergunta

Em suma, minha pergunta é: se você tem aula, MyClass<T>, como você pode alterar a definição de classe para apoiar casos onde você tem MyClass<T, Alloc>, semelhante a como, digamos, o STL Vector fornece.

Preciso dessa funcionalidade para suportar um alocador para memória compartilhada. Especificamente, estou tentando implementar um buffer de anel na memória compartilhada. Atualmente, ele tem o seguinte cTOR:

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

Onde ItemType é o tipo de dados a serem colocados em cada slot do buffer.

Agora, isso funciona esplêndido quando eu crio o buffer do programa principal, assim

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

No entanto, neste caso, o próprio buffer não é criado na memória compartilhada e, portanto, não é acessível a outros processos. O que eu quero fazer é poder fazer 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);

No entanto, não sei como adicionar um alocador explícito ao modelo de classe.

Foi útil?

Solução

O que me faz confundir é: por que você precisa alocar ou criar um objeto em SharedMemory (SHM), por exemplo, se você reservar uma memória compartilhada dos bytes tamanho 65536, suponha que você obtenha sua memória compartilhada no endereço 0x1ABC0000, se o sucesso da reserva, você terá espaço de memória gratuito e diretamente acessível em 0x1ABC0000 to 0x1ABCFFFF.

Então, quando seu aplicativo precisar "alocar" o objeto em SHM de tamanho sizeof(SHMObject), e seu gerente de memória, veja esse endereço em 0x1ABC0000+0x1A é gratuito, seu gerente de memória deve apenas retornar 0x1ABC001A valor e marca ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) ) estava ocupado e você só precisa lançar: SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);

e é claro que assume que você tem seu próprio alocador de memória personalizado que funciona no intervalo especificado do endereço de memória.

Quanto ao modelo, eu realmente não entendo como é o seu buffer de anel shm, mas eu fiz isso antes de usar o SHM, minha implementação é assim: `

//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);
         }
}

`

Outras dicas

Eu acho que você está apenas procurando o padrão posicionamento novo.

Se shm_addr é um void* Ponteiro para a memória compartilhada que você pode fazer:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

e o novo MyBuffer será construído no local fornecido. Isso pode funcionar com qualquer tipo de objeto, incluindo tipos modelo.

Você pode envolver isso em uma função separada se achar o ajuste.

Destruir algo criado com padrão posicionamento novo Você precisa chamar explicitamente o destruidor. Isto é porque delete tentaria desalocar a memória como regular new Memória alocada que não seria uma coisa válida a se fazer. Esta é a única vez em C ++ que você precisa chamar explicitamente de um destruidor.

pBuf->~MyBuffer();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top