向创建共享内存对象的C ++类模板添加一个分配器 [英] Adding an allocator to a C++ class template for shared memory object creation

查看:365
本文介绍了向创建共享内存对象的C ++类模板添加一个分配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简而言之,我的问题是:如果你有类, MyClass< T> ,如何更改类定义支持 MyClass< T,Alloc> ,类似于如何说,STL向量提供。



我需要此功能来支持共享内存的分配器。具体来说,我试图在共享内存中实现一个环形缓冲区。目前它有以下ctor:

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

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

解决方案

什么让我困惑的是,为什么你需要在SharedMemory(SHM)中分配或创建一个对象,保留大小为65536字节的共享内存,那么假设你在地址 0x1ABC0000 获得你的共享内存,如果保留成功,你将有空闲和直接访问的内存空间<$ c $当你的应用程序需要在SHM中分配对象大小 sizeof(c)时,c> 0x1ABC0000到0x1ABCFFFF



< SHMObject),并且你的内存管理器看到 0x1ABC0000 + 0x1A 的地址是空闲的,你的内存管理器应该返回 0x1ABC001A 的值,并且标记(0x1ABC001A到0x1ABC001A + sizeof(SHMObject))被占用,你只需要转换: SHMObject * shmObjectPtr =(SHMObject *)(0x1ABC001A);



和ofcourse,假设你有自己的自定义内存分配器内存地址范围。



对于模板,我真的不明白你的SHM环形缓冲区是什么样子,但我使用SHM之前,我的实现是这样的:
`

  // memory SHM allocator 
template< typename T> class ShmRingAllocator
{
protected:
void * baseAddress;
public:
ShmRingAllocator(void * baseAddress,int memSize);
void * allocate(); //这个函数做我之前描述的,或者你可以使用placement new:new(baseAddress + offset)T;
}

//某种类型的shared_ptr<> SHM中的句柄对象,这提供机制来检查指针在shm中是否仍然有效
template< typname T> ShmRingObjectPtr
{
protected:
T * object; //当前进程对象的映射地址
ShmBuffer * shm; //每个对象都有指向SHM的指针指向
的指针public:
virtual T * operator->(); //操作符重载访问T对象
}

类ShmBuffer //所有种类的SHM缓冲区的基类
{
protected:
std: :string shmName;
void * shmBasePtr;
}

template< typename T,class A = ShmRingAllocator< T> ShmRingBuffer:public ShmBuffer
{
protected:
分配器;
public:
ShmRingObjectPtr< T> insert()//将一个元素推送到环形缓冲区
{
return ShmRingObjectPtr< T>((T *)this-> allocator.allocate(),this);
}
}

`


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.

解决方案

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

`

这篇关于向创建共享内存对象的C ++类模板添加一个分配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆