私の関数には静的な変数がありますが、スレッドごとに静的にしたいです。
各スレッドが独自のクラスインスタンスのコピーを持つように、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です。
#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();
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
boost::thread_specific_ptr
は、ポータブルなソリューションとして最適な方法です。
LinuxおよびGCCでは、 __thread
修飾子 。
したがって、インスタンス変数は次のようになります。
static __thread MyClass *instance = new MyClass();
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();
}
C++ 11は thread_local
ストレージタイプ、そのまま使用します。
AnotherClass::threadSpecificAction()
{
thread_local MyClass *instance = new MyClass();
instance->doSomething();
}
オプションの最適化の1つは、スレッドローカルストレージにも割り当てることです。
Windowsでは、 TlsAlloc および TlsFree を使用して、スレッドのローカルストレージにストレージを割り当てることができます。
TLSを使用して値を設定および取得するには、それぞれ TlsSetValue および TlsGetValue を使用できます
ここ 使用方法の例を見ることができます。
ちょっとした注意... 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を含むことができません。
Folly(Facebook Open-source Library) は、スレッドローカルストレージの移植可能な実装を備えています。
その著者によると:
自明ではない型のスレッドローカルストレージの改善(
pthread_getspecific
ただし、単一のpthread_key_t
、およびboost::thread_specific_ptr
)。
ローカルストレージスレッドの移植可能な実装を探している場合、このライブラリは適切なオプションです。