Hinzufügen eines Allocators zu einer C ++ - Klassenvorlage für die Erstellung gemeinsamer Speicherobjekte

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

  •  19-09-2019
  •  | 
  •  

Frage

Kurz gesagt, meine Frage lautet: Wenn Sie Unterricht haben, MyClass<T>, wie können Sie die Klassendefinition ändern, um Fälle zu unterstützen, in denen Sie haben? MyClass<T, Alloc>, ähnlich wie beispielsweise STL Vector bietet.

Ich brauche diese Funktionalität, um einen Allocator für gemeinsam genutztes Speicher zu unterstützen. Insbesondere versuche ich, einen Ringpuffer im gemeinsamen Speicher zu implementieren. Derzeit hat es das folgende CTOR:

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

wo ItemType ist der Typ der Daten, die in jedem Schlitz des Puffers platziert werden sollen.

Nun, dies funktioniert großartig, wenn ich den Puffer aus dem Hauptprogramm so erstelle

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

In diesem Fall wird der Puffer selbst jedoch nicht im gemeinsamen Speicher erstellt und ist daher nicht für andere Prozesse zugänglich. Was ich tun möchte, ist in der Lage zu sein, so etwas zu tun

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

Ich weiß jedoch nicht, wie ich der Klassenvorlage einen expliziten Allocator hinzufügen soll.

War es hilfreich?

Lösung

Was mich verwirrt, ist, warum Sie ein Objekt in SharedMemory (SHM) zuweisen oder erstellen müssen, beispielsweise wenn Sie den gemeinsamen Speicher der Größe 65536 Bytes reservieren, dann nehmen Sie an, dass Sie Ihren gemeinsamen Speicher unter der Adresse erhalten 0x1ABC0000, Wenn der Reservierungserfolg einen kostenlosen und direkt zugänglichen Speicherplatz erhalten 0x1ABC0000 to 0x1ABCFFFF.

Wenn Ihre Anwendung dann Objekt in SHM der Größe "zuordnen" muss sizeof(SHMObject), und Ihr Speichermanager sehen diese Adresse unter 0x1ABC0000+0x1A ist kostenlos, Ihr Speichermanager sollte einfach zurückkehren 0x1ABC001A Wert und Marke ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) ) war besetzt und Sie müssen nur besetzen: SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);

und natürlich wird davon ausgegangen, dass Sie einen eigenen benutzerdefinierten Speicher -Allocator haben, der an der angegebenen Speicherbeschaffungsrede arbeitet.

Was die Vorlage betrifft, verstehe ich nicht wirklich, wie Ihr SHM -Ringpuffer aussieht, aber ich habe das vor der Verwendung von SHM getan, meine Implementierung ist wie folgt: `

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

`

Andere Tipps

Ich denke, dass Sie nur nach dem Standard suchen Platzierung neu.

Wenn shm_addr ist ein void* Zeiger auf gemeinsamen Speicher, den Sie tun können:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

und das neue MyBuffer wird am gegebenen Ort gebaut. Dies kann mit jeder Art von Objekt, einschließlich Vorlagen -Typen, funktionieren.

Sie können dies in eine separate Funktion einwickeln, wenn Sie Fit sehen.

Etwas zu zerstören, das mit Standard geschaffen wurde Platzierung neu Sie müssen den Destruktor explizit anrufen. Das ist weil delete Würde versuchen, den Speicher als regulär zu verkünden new Zugewiesener Gedächtnis, der keine gültige Sache wäre. Dies ist das einzige Mal in C ++, das Sie explizit einen Destruktor nennen müssen.

pBuf->~MyBuffer();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top