4

この質問の背景が役立つ場合があります。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 は許可されません。

4

0 に答える 0