4

简而言之,我的问题是:如果你有类,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);

但是,我不知道如何将显式分配器添加到类模板中。

4

2 回答 2

5

我认为您只是在寻找标准位置 new

如果shm_addrvoid*指向共享内存的指针,您可以执行以下操作:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

新的MyBuffer将在给定的位置建造。这适用于任何类型的对象,包括模板类型。

如果您认为合适,您可以将其包装在一个单独的函数中。

要销毁使用标准放置 new创建的东西,您需要显式调用析构函数。这是因为delete会尝试将内存重新分配为常规new分配的内存,这不是一个有效的做法。这是 C++ 中唯一一次需要显式调用析构函数。

pBuf->~MyBuffer();
于 2010-03-11T07:48:54.270 回答
3

让我感到困惑的是,为什么需要在 SharedMemory (SHM) 中分配或创建对象,例如,如果您保留大小为 65536 字节的共享内存,那么假设您在 address 获得共享内存0x1ABC0000,如果保留成功,您将拥有的免费且可直接访问的内存空间0x1ABC0000 to 0x1ABCFFFF

然后,当您的应用程序需要在 SHM 中“分配” size 的对象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);
         }
}

`

于 2010-03-11T11:12:51.770 回答