0

std::allocator ( MAllocatorに基づく)の実装は、共有メモリという名前の Windows によってサポートされ、MAllocator にいくつかの項目を追加します。

  • allocate()の追加のパラメータは、std::allocator の署名を変更します。アロケータは通常テンプレート パラメータであることを考えると、これで問題ありませんか (エラーはコンパイル時にキャッチされます)。

    template<class T> T *allocate(const size_t n, const char* name);

  • 状態は、deallocate() のハンドルへのポインターのマップの形式で維持されます。アロケータは、状態の整合性を維持するために、他のインスタンスとの等価性を拒否します。これで十分ですか、それとも追加の保護手段が必要ですか?

    typedef std::map<uintptr_t, HANDLE> HandleMap;
    HandleMap mHandles;
    
    deallocate(T *const p, size_t n = 0) 
    {
        if (mHandles.find((uintptr_t)p) == mHandles.end())  //we don't own this pointer
        {
            std::ostringstream msg;
            msg << "Error in deallocate(): Invalid pointer - we don't own it - we can't delete it!";
            throw std::exception(msg.str().c_str() );
        }
    
        unmapView(p);
        closeHandle(p);
        mHandles.erase((uintptr_t)p);
    }
    

githubの完全なコード

4

1 に答える 1

1

まず、あなたの質問は「std::allocator の場合」と言っていますが、これは ではなく、std::allocatorですShmAllocatorstd::allocatorは標準ライブラリによって提供されるクラス テンプレートです。アロケータはそのクラス テンプレートではなく、別の型です。「アロケーター用」または単に「標準アロケーター用」を意味していると思います。これは、アロケーターの要件に準拠するタイプを指します(std::allocatorそのようなタイプの一例にすぎません。)

これはアロケーターの要件を満たしていません。具体的には、コピーは元のオブジェクトと等しくありません。標準準拠のアロケーターを期待するコードでこのアロケーターを使用する場合、失敗する可能性があります。標準のアロケーターを期待するコードで使用する予定がない場合、わざわざそのインターフェースをコピーする必要はありません。

コピー コンストラクターの要件では、aShmAllocator<T>のオブジェクトに対してステートメントShmAllocator<T> a1(a);が有効であり、事後条件が であることa1 == a、およびbShmAllocator<U>のオブジェクトに対してステートメントShmAllocator<T> a(b);が有効であり、事後条件がShmAllocator<U>(a) == bおよびであることを要求しますa == ShmAllocator<T>(b)

これらの要件が必要なのは、コンテナーがアロケーターを再バインドし、互いのメモリを解放できる必要があるコピーを作成できる必要があるためです。ステートフル アロケーターの等価性は、ID ではなく値に依存する必要があります。

アロケーターのコピーがすべて同じコレクションを共有できるように、アロケーターをmHandles保存できる要件を満たすようにします。shared_ptr<mHandles>

このアロケーターをどのように使用する予定ですか? Windows API 関数はわかりませんが、呼び出すたびallocateに別の値を使用する必要があるようですname。そうしないと、同じポインターが返されます。つまり、標準のコンテナーでは使用できません。共有メモリ アロケータは、そのコンストラクタで共有メモリ領域を作成し (または、既存の領域への参照を使用して構築されます。たとえば、Boost.Interprocess アロケータを参照してください)、その領域を分割して、毎回異なるチャンクを返します。allocateを呼び出すたびに新しいリージョンを作成するのではなく、 が呼び出されallocateます。これは、プロセス間でオブジェクトを共有するためのユーザーになることを意図していますか? 別のプロセスが既存のオブジェクトにアクセスするにはどうすればよいでしょうか? 他のプロセスが呼び出す必要があるようですallocate既に構築されたオブジェクトへのポインターを取得します。それは紛らわしいallocateです。初期化されていない新しいメモリが必要です。共有メモリ アロケータは通常、オフセットを絶対アドレスではなく共有メモリ領域に格納するカスタム ポインタ タイプを定義します。別のアドレスにマッピングされます。

于 2012-06-17T19:18:57.433 に答える