4

要するに、私の質問は次のとおりです。クラスがある場合、たとえばSTLベクトルが提供する方法と同様にMyClass<T>、クラス定義を変更して、ある場合をサポートするにはどうすればよいですか。MyClass<T, Alloc>

共有メモリのアロケータをサポートするには、この機能が必要です。具体的には、共有メモリにリングバッファを実装しようとしています。現在、次の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);

ただし、クラステンプレートに明示的なアロケータを追加する方法がわかりません。

4

2 に答える 2

5

新しい標準配置を探しているだけだと思います。

shm_addrが共有メモリへのポインタである場合、次のvoid*ことができます。

MyBuffer *pBuf = new (shm_Addr) MyBuffer;

そして、新しいMyBufferものは指定された場所に建設されます。これは、テンプレートタイプを含むすべてのタイプのオブジェクトで機能します。

適切と思われる場合は、これを別の関数でラップできます。

新しい標準配置で作成されたものを破棄するには、デストラクタを明示的に呼び出す必要があります。これはdelete、メモリを通常の割り当て済みメモリとして割り当て解除しようとするためですが、これはnew有効なことではありません。これは、C++でデストラクタを明示的に呼び出す必要がある唯一の時間です。

pBuf->~MyBuffer();
于 2010-03-11T07:48:54.270 に答える
3

私を混乱させるのは、SharedMemory(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);
         }
}

`

于 2010-03-11T11:12:51.770 に答える