2010-03-11 58 views
3

總之,我的問題是:如果您有類MyClass<T>,如何更改類定義以支持您有MyClass<T, Alloc>的情況,類似於說,STL向量提供。將分配器添加到C++類模板以創建共享內存對象

我需要此功能來支持共享內存的分配器。具體來說,我試圖在共享內存中實現一個環形緩衝區。目前,它具有以下的構造函數:

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

不過,我不知道如何去增加一個明確分配給類模板。

+0

我不太明白你在問什麼。你是否需要知道如何將模板參數添加到類模板中(在這種情況下,您可能需要顯示該類的當前定義),還是隻需要知道如何在內存中的給定位置構造對象(在這種情況下,您應該搜索_placement new_)。無論哪種方式,我都會非常謹慎地將非POD對象放在共享內存中。是否有可能從一個過程構建並從另一個過程中摧毀?你完全確定所有的班級成員都可以處理這個問題嗎? – 2010-03-11 07:44:24

+0

我想我的問題可以簡單地轉述爲:如何在共享內存中創建對象(與在當前進程堆上創建它並使用共享內存相對)。 – recipriversexclusion 2010-03-11 07:44:39

+0

在這種情況下,您需要新放置。例如如果'shm_addr'是共享內存的'void *'指針,你可以使用'MyBuffer * pBuf = new(shm_Addr)MyBuffer;'和新的'MyBuffer'將在給定的位置構造。 – 2010-03-11 07:46:44

回答

3

什麼讓我迷惑的是,爲什麼你需要的,如果你預留大小65536字節的共享內存來分配或創建共享內存(SHM)的對象,例如,那麼假設你在地址讓你的共享內存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); 
     } 
} 

`

+0

您的SHM緩衝區原型非常有用,謝謝!我有點理解你使用自定義SHM分配器實現它的方式。我無法理解的是,你如何從不同的流程,作者和讀者訪問ShmBuf。比方說,我在作者中創建了ShmBuf,並在其中插入了元素。獨立閱讀器如何訪問該對象並從中讀取數據(您似乎還沒有pop()成員)。 – recipriversexclusion 2010-03-11 13:52:14

+0

如果你想讓不同的進程能夠讀寫,我通過創建offset_ptr <>來解決它,這又如shared_ptr <>但包含64位指針地址(在x86平臺上),首先它包含shm基地址,第二個包含偏離基地址的地址,通過使用這個,你可以在shmBUffer中使用或者寫一個指向shmBUffer數據的指針,這樣shm裏面的所有指針都會指向shmBuffer中的相同數據,因爲它使用它們自己的偏移量地址在每個過程中。其餘的幾乎都是同步的,因爲你在處理器之間具有幾乎確切的存儲空間 – uray 2010-03-12 04:34:31

4

我認爲你只是尋找標準安置新

如果shm_addrvoid*指向共享內存,你可以這樣做:

MyBuffer *pBuf = new (shm_Addr) MyBuffer; 

和新MyBuffer將在指定的位置來構建。這可以用於任何類型的對象,包括模板類型。

如果您覺得合適,您可以將其封裝在單獨的功能中。

要摧毀用標準放置新的創建的東西,您需要顯式調用析構函數。這是因爲delete會嘗試將內存取消分配爲常規的new分配的內存,這不是一個有效的事情。這是C++中唯一需要顯式調用析構函數的時間。

pBuf->~MyBuffer(); 
+0

我認爲這是我正在尋找的。不知道你可以爲'new'指定一個addr位置,哇。謝謝! – recipriversexclusion 2010-03-11 07:50:20