代码之家  ›  专栏  ›  技术社区  ›  recipriversexclusion

将一个分配器添加到C++类模板中,用于共享内存对象创建

  •  3
  • recipriversexclusion  · 技术社区  · 16 年前

    总之,我的问题是:如果你有课, 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 回复  |  直到 12 年前
        1
  •  3
  •   uray    16 年前

    让我困惑的是,为什么您需要在shared memory(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);
             }
    }
    

    `

        2
  •  4
  •   CB Bailey    16 年前

    我想你只是在找标准 新位置 .

    如果 shm_addr 是一个 void* 指向共享内存的指针:

    MyBuffer *pBuf = new (shm_Addr) MyBuffer;
    

    和新的 MyBuffer 将在指定位置建造。这可以用于任何类型的对象,包括模板化类型。

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

    摧毁用标准创造的东西 新位置 您需要显式调用析构函数。这是因为 delete 将尝试按常规取消分配内存 new 分配的内存不是有效的操作。这是C++中唯一需要显式调用析构函数的时间。

    pBuf->~MyBuffer();