この質問の背景が役立つ場合があります。C++ で記述されたマルチスレッド アプリケーションがあり、パフォーマンスの点でメモリ管理が重要なポイントです。私はすでに「メイン」アロケーターを実装しています。それが「ManagedAllocator」と呼ばれていると仮定しましょう。また、 CPU レジスタasm
を使用して記述された、独自のマルチプラットフォーム スレッド ローカル ストレージ サポートもあります。fs
基本的に、グローバル演算子 new は次のようになります。
void* operator new(Size_t memSize)
{
Thread_data& tls = get_thread_local_data();
ManagedAllocator* allocator = tls[TLS_INDEX_MANAGED_ALLOCATOR];
return allocator->AllocateMemory(memSize);
}
アロケータのローカル インスタンスの作成と破棄は、各スレッドによって実行されます。これは、標準のアロケーター (Win7/8、Linux、MacOS、および WP8 (TLS の実装がわずかに異なる) で既にテスト済み) と比較して、非常に素晴らしく、超高速に機能します。
さて、問題:私は次のクラスを持っています:
template < Size_t Alloc_size >
class FixedPoolAllocator
{
};
このクラスは ManagedAllocator によって内部的に使用されていましたが、最近、スタンドアロンのアロケーターとしても使用する必要があることがわかりました。ただし、FixedPoolAllocator の特殊化ごとに TLS 配列で 1 つのスロットを使用する必要があるため、ManagedAllocator と同じ方法では実行できません。
ただし、ロックをいじりたいとは思いません。ロックフリーの割り当てが必要だからです。これをクリーンでエレガントな方法で行う方法はありますか?
* アップデート *
1 つ言い忘れていたことがあります。それは、私が本当にしなければならないことです。
私は単純なクラスを持っています:
template < class Allocator >
class EXS_INTERFACE CustomAllocObject
{
public:
explicit CustomAllocObject();
~CustomAllocObject();
static void* operator new(Size_t memSize);
//also new[], placement versions, etc.
static void operator delete(void* memPtr);
//same as above
};
これは単純に次のことを行います:
template < class Allocator >
_EXSTemplateDef void*
CustomAllocObject<Allocator>::operator new(Size_t memSize)
{
return Allocator::AllocateMemory(memSize);
}
これを使用して、高速割り当てが必要なオブジェクトを作成します。
class Image : public CustomAllocObject< FixedSizeAllocator<sizeof(ImageInternal)> >
{
};
AllocateMemory() は、各アロケーター クラスの静的関数です。したがって、完璧な解決策は次のとおりです。
template < Size_t Alloc_size >
_EXSTemplateDef void*
FixedPoolAllocator<Alloc_size>::AllocateMemory(Size_t memSize)
{
FixedPoolAllocator<Alloc_size>* alloc = get_somehow_this_threads_instance();
return alloc->PerformAllocation();
}
問題は、私はこれを行うことができないということです:
template < Size_t Alloc_size >
class FixedPoolAllocator
{
//....
static EXS_THREAD_LOCAL FixedPoolAllocator<Alloc_size> _local_instance;
};
ライブラリはDLLにコンパイルされるためです。この場合、FixedPoolAllocator は DLL_EXPORT クラスであり (つまり、すべての静的メンバーもそうであることを意味します)、DLL_EXPORTed THREAD_LOCAL は許可されません。