nlib
misc/threading/callonce/callonce.cpp

nlib_once()のサンプルです。pthreadのpthread_onceに相当します。

nlib_once()は初期化コードが高々1回しか実行されないようにすることに利用されます。 サンプルでは複数立ち上がったスレッドがいずれもnlib_once経由でOnceFuncを呼び出そうとしますが、実際に実行するのは最初に到達したスレッドのみです。

他のスレッドはnlib_onceflagの実行中はスピンして待ち、実行完了後にnlib_once以降の処理を実行します。 つまり、nlib_onceの実行後にはOnceFuncが必ず1回だけ呼び出されていることが保証されています。

using ::nlib_ns::threading::Thread;
const int NUM_THREAD = 8;
Thread g_Th[NUM_THREAD];
// Initializes statically to avoid race condition.
// g_OnceFlag will be changed by nlib_once atomically.
void OnceFunc() {
// OnceFunc called only once
nlib_printf("OnceFunc start\n");
nlib_printf("OnceFunc end\n");
}
void ThreadFunc() {
nlib_printf("Thread #%d: start\n", th);
// executes OnceFunc if not executed.
// does nothing if OnceFunc already executed
// spins and waits if OnceFunc is executing
nlib_once(&g_OnceFlag, OnceFunc);
// nlib_once confirms 'OnceFunc' is executed only once at this point.
nlib_printf("Thread #%d: end\n", th);
}
bool CallOnceDemo() {
nlib_printf("%d threads tries to execute 'OnceFunc'\n", NUM_THREAD);
nlib_printf("nlib_once executes 'OnceFunc' only once\n\n");
int i;
for (i = 0; i < NUM_THREAD; ++i) {
g_Th[i].Start(ThreadFunc);
}
for (i = 0; i < NUM_THREAD; ++i) {
g_Th[i].Join();
}
ThreadFunc();
return true;
}
static bool SampleMain(int, char**) { return CallOnceDemo(); }
NLIB_MAINFUNC