L'aggiunta di un allocatore a un C ++ classe template per la creazione di oggetti di memoria condivisa

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

  •  19-09-2019
  •  | 
  •  

Domanda

In breve, la mia domanda è: se si dispone di classe, MyClass<T>, come si può cambiare la definizione della classe per supportare i casi in cui si dispone MyClass<T, Alloc>, in modo simile a come, per esempio, STL vettore fornisce.

Ho bisogno di questo funzionalità per supportare un allocatore per la memoria condivisa. In particolare, sto cercando di implementare un buffer circolare nella memoria condivisa. Attualmente ha il seguente ctor:

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

dove ItemType è il tipo di dati da inserire in ciascuno slot del buffer.

Ora, questo funziona splendida quando creo il buffer dal programma principale quindi

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

Tuttavia, in questo caso il buffer stesso non viene creata nella memoria condivisa e quindi non è accessibile ad altri processi. Quello che voglio fare è quello di essere in grado di fare qualcosa di simile

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

Tuttavia, non so come fare per aggiungere un allocatore esplicito al modello di classe.

È stato utile?

Soluzione

quello che mi fanno confondere è, perché è necessario allocare o creare un oggetto in SharedMemory (SHM), ad esempio, se si riserva di memoria condivisa della dimensione 65536 byte, quindi suppongo che si ottiene la memoria condivisa all'indirizzo 0x1ABC0000, se la prenotazione il successo si avrà memoria libera e direttamente accessibile a 0x1ABC0000 to 0x1ABCFFFF.

poi, quando l'applicazione ha bisogno di "allocare" oggetto in SHM di dimensioni sizeof(SHMObject), e il vostro gestore di memoria vedere che indirizzo al 0x1ABC0000+0x1A è gratuito, il gestore di memoria deve solo restituire valore 0x1ABC001A, e segnare ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) ) è stato occupato, e basta per lanciare: SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);

e naturalmente che sta assumendo hai il tuo allocatore di memoria personalizzato che funziona su gamma specificata di indirizzi di memoria.

Per quanto riguarda il modello, io non capisco come fa il vostro buffer circolare SHM sembrare, ma l'ho fatto prima di usare SHM, la mia implementazione è simile a questo: `

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

`

Altri suggerimenti

Credo che sono solo alla ricerca per lo standard nuova collocazione .

Se shm_addr è un puntatore void* alla memoria condivisa si può fare:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

e il nuovo MyBuffer verrà costruito alla posizione indicata. Questo può funzionare con qualsiasi tipo di oggetto, compresi i tipi su modelli.

È possibile avvolgere questo in una funzione separata, se si vede in forma.

Per distruggere qualcosa creato con posizionamento standard nuovo è necessario chiamare in modo esplicito il distruttore. Questo perché delete avrebbe cercato di de-allocare la memoria, come regolare new memoria allocata che non sarebbe una cosa valida da fare. Questa è l'unica volta in C ++ che è necessario chiamare esplicitamente un distruttore.

pBuf->~MyBuffer();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top