web-dev-qa-db-ja.com

スレッドローカルストレージを割り当てる方法

私の関数には静的な変数がありますが、スレッドごとに静的にしたいです。

各スレッドが独自のクラスインスタンスのコピーを持つように、C++クラスにメモリを割り当てるにはどうすればよいですか?

AnotherClass::threadSpecificAction()
{
  // How to allocate this with thread local storage?
  static MyClass *instance = new MyClass();

  instance->doSomething();
}

これはLinux上にあります。私はC++ 0xを使用していません。これはgcc v3.4.6です。

56
WilliamKF
#include <boost/thread/tss.hpp>
static boost::thread_specific_ptr< MyClass> instance;
if( ! instance.get() ) {
    // first time called by this thread
    // construct test element to be used in all subsequent calls from this thread
    instance.reset( new MyClass);
}
    instance->doSomething();
67
ravenspoint

C++ 11がthread_localキーワードを導入することは注目に値します。

ストレージ期間指定子 の例を次に示します。

#include <iostream>
#include <string>
#include <thread>
#include <mutex>

thread_local unsigned int rage = 1; 
std::mutex cout_mutex;

void increase_rage(const std::string& thread_name)
{
    ++rage;
    std::lock_guard<std::mutex> lock(cout_mutex);
    std::cout << "Rage counter for " << thread_name << ": " << rage << '\n';
}

int main()
{
    std::thread a(increase_rage, "a"), b(increase_rage, "b");
    increase_rage("main");

    a.join();
    b.join();

    return 0;
}

可能な出力:

Rage counter for a: 2
Rage counter for main: 2
Rage counter for b: 2
64
Deqing

boost::thread_specific_ptr は、ポータブルなソリューションとして最適な方法です。

LinuxおよびGCCでは、 __thread修飾子

したがって、インスタンス変数は次のようになります。

static __thread MyClass *instance = new MyClass();
14
tvn

Pthreadsを使用している場合、次のことができます。

//declare static data members
pthread_key_t AnotherClass::key_value;
pthread_once_t AnotherClass::key_init_once = PTHREAD_ONCE_INIT;

//declare static function
void AnotherClass::init_key()
{
    //while you can pass a NULL as the second argument, you 
    //should pass some valid destrutor function that can properly
    //delete a pointer for your MyClass
    pthread_key_create(&key_value, NULL);
}

void AnotherClass::threadSpecificAction()
{
  //Initialize the key value
  pthread_once(&key_init_once, init_key);

  //this is where the thread-specific pointer is obtained
  //if storage has already been allocated, it won't return NULL

  MyClass *instance = NULL;
  if ((instance = (MyClass*)pthread_getspecific(key_value)) == NULL)
  {
    instance = new MyClass;
    pthread_setspecific(key_value, (void*)instance);
  }

  instance->doSomething();
}
11
Jason

C++ 11は thread_local ストレージタイプ、そのまま使用します。

AnotherClass::threadSpecificAction()
{
  thread_local MyClass *instance = new MyClass();
  instance->doSomething();
}

オプションの最適化の1つは、スレッドローカルストレージにも割り当てることです。

4
Arne

MSVC++を使用している場合は、 スレッドローカルストレージ(TLS) と読むことができます。

そして、あなたはこれを見ることができます

また、 TLSのルールと制限 に注意してください

3
Nawaz

Windowsでは、 TlsAlloc および TlsFree を使用して、スレッドのローカルストレージにストレージを割り当てることができます。

TLSを使用して値を設定および取得するには、それぞれ TlsSetValue および TlsGetValue を使用できます

ここ 使用方法の例を見ることができます。

3
Tony The Lion

ちょっとした注意... MSVC++はVSC++ 2005のdeclspec(thread)をサポートしています

#if (_MSC_VER >= 1400)
  #ifndef thread_local     
    #define thread_local __declspec(thread)
  #endif
#endif

主な問題は(boost :: thread_specific_ptrで解決されます)それでマークされた変数はctorまたはdtorを含むことができません。

2
Arek Bal

Folly(Facebook Open-source Library) は、スレッドローカルストレージの移植可能な実装を備えています。

その著者によると:

自明ではない型のスレッドローカルストレージの改善(pthread_getspecificただし、単一のpthread_key_t、およびboost::thread_specific_ptr)。

ローカルストレージスレッドの移植可能な実装を探している場合、このライブラリは適切なオプションです。

1
chema989