Добавление распределителя в шаблон класса C ++ для создания объекта общей памяти - PullRequest
3 голосов
/ 11 марта 2010

Короче говоря, мой вопрос: если у вас есть класс, MyClass<T>, как вы можете изменить определение класса для поддержки случаев, когда у вас есть MyClass<T, Alloc>, аналогично тому, как, скажем, вектор STL.

Мне нужна эта функциональность для поддержки распределителя для разделяемой памяти. В частности, я пытаюсь реализовать кольцевой буфер в разделяемой памяти. В настоящее время он имеет следующий ctor:

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

где ItemType - это тип данных, которые должны быть помещены в каждый слот буфера.

Теперь это работает великолепно, когда я создаю буфер из основной программы, таким образом

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

Однако в этом случае сам буфер не создается в общей памяти и поэтому не доступен для других процессов. Что я хочу сделать, так это уметь делать что-то вроде

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

Однако я не знаю, как добавить явный распределитель в шаблон класса.

Ответы [ 2 ]

5 голосов
/ 11 марта 2010

Я думаю, что вы просто ищете стандартное новое размещение .

Если shm_addr является void* указателем на разделяемую память, вы можете сделать:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

и новый MyBuffer будет построен в данном месте. Это может работать с любым типом объекта, включая шаблонные типы.

Вы можете обернуть это в отдельную функцию, если считаете нужным.

Чтобы уничтожить что-то, созданное с помощью стандартного размещения нового , вам нужно явно вызвать деструктор. Это связано с тем, что delete попытался бы выделить память как обычную new выделенную память, что было бы недопустимым. Это единственный раз в C ++, когда вам нужно явно вызвать деструктор.

pBuf->~MyBuffer();
3 голосов
/ 11 марта 2010

меня сбивает с толку то, что вам нужно выделить или создать объект в SharedMemory (SHM), например, если вы резервируете разделяемую память размером 65536 байт, тогда предположим, что вы получаете разделяемую память по адресу 0x1ABC0000, в случае успешного бронирования у вас будет свободное и непосредственно доступное пространство памяти на 0x1ABC0000 to 0x1ABCFFFF.

тогда, когда вашему приложению нужно «выделить» объект в SHM размером sizeof(SHMObject), и ваш менеджер памяти увидит, что адрес на 0x1ABC0000+0x1A свободен, ваш менеджер памяти должен просто вернуть значение 0x1ABC001A и отметить ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) ) был занят, и вам просто нужно разыграть: SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);

и, конечно, при условии, что у вас есть собственный распределитель памяти, работающий с указанным диапазоном адресов памяти.

Что касается шаблона, я не очень понимаю, как выглядит ваш кольцевой буфер SHM, но я сделал это, прежде чем использовать SHM, моя реализация выглядит так: `

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

`

...