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

发布于 2024-08-24 12:44:30 字数 1047 浏览 5 评论 0原文

简而言之,我的问题是:如果您有类 MyClass,如何更改类定义以支持您有 MyClass 的情况,类似于 STL 矢量提供的方式。

我需要此功能来支持共享内存分配器。具体来说,我正在尝试在共享内存中实现环形缓冲区。目前它具有以下构造函数:

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

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

In short, my question is: If you have class, MyClass<T>, how can you change the class definition to support cases where you have MyClass<T, Alloc>, similar to how, say, STL vector provides.

I need this functionality to support an allocator for shared memory. Specifically, I am trying to implement a ring buffer in shared memory. Currently it has the following ctor:

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

where ItemType is the type of the data to be placed in each slot of the buffer.

Now, this works splendid when I create the buffer from the main program thus

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

However, in this case the buffer itself is not created in shared memory and so is not accessible to other processes. What I want to do is to be able to do something like

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

However, I don't know how to go about adding an explicit allocator to the class template.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

简美 2024-08-31 12:44:30

我认为您只是在寻找标准的新展示位置

如果 shm_addr 是一个指向共享内存的 void* 指针,您可以这样做:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

并且新的 MyBuffer 将在给定位置构造。这可以适用于任何类型的对象,包括模板化类型。

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

要销毁使用标准放置 new 创建的内容,您需要显式调用析构函数。这是因为 delete 会尝试将内存作为常规new 分配的内存来取消分配,这不是有效的操作。这是 C++ 中唯一一次需要显式调用析构函数。

pBuf->~MyBuffer();

I think that you are just looking for the standard placement new.

If shm_addr is a void* pointer to shared memory you can do:

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

and the new MyBuffer will be constructed at the given location. This can work with any type of object, including templated types.

You can wrap this in a separate function if you see fit.

To destroy something created with standard placement new you need to explicitly call the destructor. This is because delete would try to de-allocate the memory as regular new allocated memory which wouldn't be a valid thing to do. This is the only time in C++ that you need to explicitly call a destructor.

pBuf->~MyBuffer();
埖埖迣鎅 2024-08-31 12:44:30

让我困惑的是,为什么你需要在 SharedMemory (SHM) 中分配或创建一个对象,例如,如果你保留大小为 65536 字节的共享内存,那么假设你在地址 0x1ABC0000,如果预约成功,您将在 0x1ABC0000 至 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);
         }
}

`

what make me confuse is, why you need to allocate or create an object in SharedMemory (SHM), for example if you reserve shared memory of the size 65536 Bytes, then suppose you get your shared memory at address 0x1ABC0000, if reservation success you will have free and directly accessible memory space at 0x1ABC0000 to 0x1ABCFFFF.

then when your application need to "allocate" object in SHM of size sizeof(SHMObject), and your memory manager see that address at 0x1ABC0000+0x1A is free, your memory manager should just return 0x1ABC001A value, and mark ( 0x1ABC001A to 0x1ABC001A+sizeof(SHMObject) ) was occupied, and you just need to cast: SHMObject* shmObjectPtr = (SHMObject*)(0x1ABC001A);

and ofcourse that is assuming you have your own custom memory allocator that work on specified range of memory address.

as for template, i don't really understand how does your SHM ring buffer look like, but I've done that before using SHM, my implementation is like this:
`

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

`

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文