C++ 将分配器添加到C++;用于创建共享内存对象的类模板
简言之,我的问题是:如果您有类,C++ 将分配器添加到C++;用于创建共享内存对象的类模板,c++,shared-memory,allocator,C++,Shared Memory,Allocator,简言之,我的问题是:如果您有类,MyClass,如何更改类定义以支持您有MyClass的情况,类似于STL vector提供的方式 我需要这个功能来支持共享内存的分配器。具体来说,我试图在共享内存中实现一个环形缓冲区。目前它有以下特点: template<typename ItemType> SharedMemoryBuffer<ItemType>::SharedMemoryBuffer( unsigned long capacity, std::string name
MyClass
,如何更改类定义以支持您有MyClass
的情况,类似于STL vector提供的方式
我需要这个功能来支持共享内存的分配器。具体来说,我试图在共享内存中实现一个环形缓冲区。目前它有以下特点:
template<typename ItemType>
SharedMemoryBuffer<ItemType>::SharedMemoryBuffer( unsigned long capacity, std::string name )
但是,在这种情况下,缓冲区本身不是在共享内存中创建的,因此其他进程无法访问。我想做的是能够做像
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);
typedef分配器ShmemAllocator;
typedef SharedMemoryBuffer MyBuffer;
托管共享内存段(仅创建“MySharedMemory”,65536);
const ShmemAllocator alloc_inst(段.get_段管理器());
MyBuffer*mybuf=segment.construct(“MyBuffer”)(alloc_inst);
但是,我不知道如何向类模板添加显式分配器 我认为您只是在寻找新的标准位置 如果
shm_addr
是指向共享内存的void*
指针,则可以执行以下操作:
MyBuffer *pBuf = new (shm_Addr) MyBuffer;
新的MyBuffer
将在给定位置构建。这可以用于任何类型的对象,包括模板化类型
如果您认为合适,可以将其包装在单独的函数中
要销毁使用标准placement new创建的内容,需要显式调用析构函数。这是因为delete
会尝试将内存作为常规new
分配的内存进行反分配,这是无效的。这是C++中唯一需要显式调用析构函数的时间。
pBuf->~MyBuffer();
让我感到困惑的是,为什么需要在SharedMemory(SHM)中分配或创建一个对象,例如,如果您保留大小为65536字节的共享内存,那么假设您的共享内存位于地址
0x1ABC0000
,如果预订成功,您将在0x1ABC0000到0x1ABCFFFF
处拥有可用的、可直接访问的内存空间
然后,当您的应用程序需要在大小为sizeof(SHMObject)
的SHM中“分配”对象,并且您的内存管理器看到0x1ABC0000+0x1A
处的地址是空闲的时,您的内存管理器只需返回0x1ABC001A
值,并标记(0x1ABC001A到0x1ABC001A+sizeof(SHMObject))
已被占用,您只需要强制转换:SHMObject*shmObjectPtr=(SHMObject*)(0x1ABC001A)代码>
当然,这是假设您有自己的自定义内存分配器,在指定的内存地址范围内工作
至于模板,我不太了解您的SHM环形缓冲区是什么样子的,但在使用SHM之前,我已经这样做了,我的实现如下:
`
//内存SHM分配器
模板类ShmRingAllocator
{
受保护的:
空*基地址;
公众:
ShmRingAllocator(void*基地址,int memSize);
void*allocate();//此函数执行我前面描述的操作,也可以使用placement new:new(baseAddress+offset)T;
}
//某种在SHM中处理对象的共享ptr,这提供了检查指针在SHM中是否仍然有效的机制
模板ShmRingObjectPtr
{
受保护的:
T*object;//当前进程中对象的映射地址
ShmBuffer*shm;//每个对象都有一个指针,该指针指向shm
公众:
虚拟T*运算符->();//访问T对象的运算符重载
}
类ShmBuffer//所有类型SHM缓冲区的基类
{
受保护的:
std::字符串shmName;
无效*shmBasePtr;
}
模板ShmRingBuffer:公共ShmBuffer
{
受保护的:
分配器;
公众:
ShmRingObjectPtr insert()//将一个元素推送到环形缓冲区
{
返回ShmRingObjectPtr((T*)this->allocator.allocate(),this);
}
}
`我不太明白你在问什么。您需要知道如何将模板参数添加到类模板中(在这种情况下,您可能需要显示类的当前定义),还是只需要知道如何在内存中的给定位置构造对象(在这种情况下,您应该搜索新位置)。无论哪种方式,我都会非常小心地将非POD对象放入共享内存。有可能从一个过程构建而从另一个过程破坏吗?你完全确定所有的类成员都能处理这个问题吗?我想我的问题可以简单地解释为:如何在共享内存中创建对象(而不是在当前进程的堆上创建对象并让它使用共享内存)。在这种情况下,你需要新的位置。e、 g.如果shm_addr
是指向共享内存的void*
指针,则可以执行MyBuffer*pBuf=new(shm_addr)MyBuffer“代码>和新的MyBuffer
将在给定位置构建。@Charles的问题变得模糊,因为我对共享内存的理解目前还不稳定。我实现了一个环形缓冲区,它使用共享内存来存储值。我希望不同的进程能够读取/写入缓冲区(实际上我有一个写入程序和多个读取程序)。我想这就是我想要的。我不知道你可以为新建
指定地址位置,哇。谢谢您的SHM缓冲原型非常有用,谢谢!我有点理解您使用自定义SHM分配器实现它的方式。我无法理解的是,您如何从不同的进程、写入程序和读取程序访问ShmBuf。比如说,我在writer中创建ShmBuf并将元素插入其中。独立的读卡器进程如何访问该对象并从中读取数据(您似乎也没有pop()成员)。如果您希望不同的进程能够写入和读取数据,我可以通过创建offset_ptr来解决此问题。这与shared_ptr类似,但包含64位指针地址(在x86平台上),
pBuf->~MyBuffer();
//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);
}
}