Ajout d'un allocateur à un modèle de classe C ++ pour la création d'objets de mémoire partagée

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

  •  19-09-2019
  •  | 
  •  

Question

En bref, ma question est: Si vous avez la classe, MyClass<T>, comment pouvez-vous changer la définition de classe pour soutenir les cas où vous avez MyClass<T, Alloc>, semblable à, disons, vecteur STL fournit.

J'ai besoin de cette fonctionnalité pour soutenir un allocateur de mémoire partagée. Plus précisément, je suis en train de mettre en œuvre un tampon circulaire dans la mémoire partagée. Actuellement, il a le cteur suivant:

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

ItemType est le type des données à placer dans chaque fente de la mémoire tampon.

Maintenant, cela fonctionne splendide lorsque je crée le tampon du programme principal ainsi

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

Cependant, dans ce cas, le tampon lui-même est pas créé dans la mémoire partagée et ainsi ne sont pas accessibles à d'autres processus. Ce que je veux faire est d'être capable de faire quelque chose comme

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

Cependant, je ne sais pas comment aller sur l'ajout d'un allocateur explicite au modèle de classe.

Était-ce utile?

La solution

ce qui fait me embrouiller, pourquoi vous avez besoin d'allouer ou de créer un objet dans SharedMemory (SHM), par exemple si vous réservez la mémoire partagée de la taille 65536 octets, supposons que vous obtenez votre mémoire partagée à l'adresse 0x1ABC0000, si la réservation succès que vous aurez l'espace mémoire libre et directement accessible à 0x1ABC0000 to 0x1ABCFFFF.

puis lorsque votre application a besoin de « allouer » objet SHM de la taille sizeof(SHMObject) et votre gestionnaire de mémoire voir cette adresse à 0x1ABC0000+0x1A est libre, votre gestionnaire de mémoire doit simplement retourner la valeur 0x1ABC001A et marque ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) ) était occupée, et vous avez juste besoin jeter: SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);

et bien sûr qui est en supposant que vous avez votre propre allocateur mémoire personnalisé qui fonctionne sur la gamme spécifiée d'adresse mémoire.

comme pour le modèle, je ne comprends pas vraiment comment votre tampon anneau SHM ressembler, mais je l'ai fait avant d'utiliser SHM, ma mise en œuvre est comme ceci: `

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

`

Autres conseils

Je pense que vous êtes à la recherche de la norme placement new .

Si shm_addr est un pointeur void* à mémoire partagée que vous pouvez faire:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

et le nouveau MyBuffer sera construit à l'endroit donné. Cela peut fonctionner avec tout type d'objet, y compris les types basés sur des modèles.

Vous pouvez envelopper cela dans une fonction distincte si bon vous semble.

Pour détruire quelque chose créé à la norme placement new vous avez besoin d'appeler explicitement le destructor. En effet, delete essaierait de désallouer la mémoire comme la mémoire allouée new régulière qui ne serait pas une chose valable de le faire. Ceci est la seule fois en C ++ que vous avez besoin d'appeler explicitement un destructor.

pBuf->~MyBuffer();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top