nlib
misc/threading/tls/tls.cpp

スレッドローカルストレージ(TLS)のサンプルです。

nn::nlib::threading::Tls<T>クラステンプレートを使うことにより、同じTls<T>のオブジェクトからスレッド毎に違うクラスTのインスタンスを参照することができます。
スレッドが終了する際、クラスTのデストラクタが自動で呼ばれるのでリソースの解放等を行うことができます。

サンプルでは、MyThreadLocalClassのコンストラクタが現在時刻をデータメンバに記録し、デストラクタにおける現在時刻との差分を計算し、コンソールに表示します。

using ::nlib_ns::threading::Tls;
using ::nlib_ns::threading::Thread;
using ::nlib_ns::DateTime;
using ::nlib_ns::TimeSpan;
class MyThreadLocalClass {
public:
MyThreadLocalClass() {
DateTime::GetNow(&m_DateTime);
}
~MyThreadLocalClass() {
// called just before a thread terminates
TimeSpan span;
DateTime dt;
DateTime::GetNow(&dt);
span = dt - m_DateTime;
nlib_printf("Thread #%d, lifetime=%d msec\n",
static_cast<int>(span.ToMilliSeconds()));
}
void DoJob(const nlib_ns::TimeSpan& span) {
}
private:
DateTime m_DateTime;
};
Tls<MyThreadLocalClass> g_ThreadLocal;
void ThreadFunc(int msec) {
// construct MyThreadLocalClass for this thread
g_ThreadLocal.Reset(new(std::nothrow) MyThreadLocalClass());
g_ThreadLocal->DoJob(TimeSpan(0, 0, msec, 0));
}
bool TlsDemo() {
Thread th1, th2, th3;
nlib_printf("MyThreadLocalClass's destructor shows messages.\n");
nlib_printf("Each thread owns MyThreadLocalClass via a Tls<MyThreadLocalClass> object\n\n");
// allocate a tls slot for g_ThreadLocal
errno_t e = g_ThreadLocal.Init();
if (e != 0) {
if (e == ENOTSUP) {
// CTR does not support destructor function
nlib_printf("It seems that nlib_tls_alloc does not support destructor function.\n");
} else {
// tls slot might be full....
}
return false;
}
th1.Start(ThreadFunc, 50);
th2.Start(ThreadFunc, 100);
th3.Start(ThreadFunc, 150);
th3.Join();
th2.Join();
th1.Join();
return true;
}
static bool SampleMain(int, char**) { return TlsDemo(); }
NLIB_MAINFUNC