nlib
misc/threading/safeinit/safeinit.cpp

複数スレッドで行われる初期化処理を安全かつ効率よく行うためのサンプルです。

nlib_once()を利用して初期化処理間の依存関係を記述し、それぞれの初期化処理を必要なときに1回だけ実行するという処理を行っています。

使い方は以下のとおりです。

  1. 初期化処理毎にタグ型を定義する。サンプル内ではa_init_tagからd_init_tagです。
  2. 各タグで実体化したSafeInitクラステンプレートごとにflag_, error_の定義を記述する。
  3. 各タグで実体化したSafeInitクラステンプレートごとにOnceFunc()関数を実装する。
  4. SafeInit<タグ型>::Init()によって初期化処理を実行することができる。

初期化順の依存関係は、nlib_once()経由で実行されるOnceFunc()内に記述します。 nlib_once()を利用するため、複数のスレッドで初期化処理を実行しても初期化関数が重複して呼び出されることはありません。

サンプル内では、a->b, a->c, b->d, c->dの依存関係が記述されています。

/*--------------------------------------------------------------------------------*
Project: CrossRoad
Copyright (C)Nintendo All rights reserved.
These coded instructions, statements, and computer programs contain proprietary
information of Nintendo and/or its licensed developers and are protected by
national and international copyright laws. They may not be disclosed to third
parties or copied or duplicated in any form, in whole or in part, without the
prior written consent of Nintendo.
The content herein is highly confidential and should be handled accordingly.
*--------------------------------------------------------------------------------*/
#include "nn/nlib/Config.h"
template<class TAG, class ERRORTYPE = bool>
class SafeInit {
public:
typedef ERRORTYPE ErrorType;
typedef TAG TagType;
static const ErrorType& Init() {
nlib_once(&flag_, OnceFunc);
return error_;
}
private:
static nlib_onceflag flag_;
static ErrorType error_;
static void OnceFunc();
};
struct a_init_tag {};
struct b_init_tag {};
struct c_init_tag {};
struct d_init_tag {};
template<> bool SafeInit<a_init_tag>::error_ = false;
template<> nlib_onceflag SafeInit<a_init_tag>::flag_ = NLIB_ONCE_INIT;
template<> void SafeInit<a_init_tag>::OnceFunc() {
nlib_printf("SafeInit<a_init_tag>::OnceFunc()\n");
}
template<> bool SafeInit<b_init_tag>::error_ = false;
template<> nlib_onceflag SafeInit<b_init_tag>::flag_ = NLIB_ONCE_INIT;
template<> void SafeInit<b_init_tag>::OnceFunc() {
bool err;
err = SafeInit<a_init_tag>::Init(); // 'b' depends 'a'.
if (err) {
error_ = true;
return;
}
nlib_printf("SafeInit<b_init_tag>::OnceFunc()\n");
}
template<> bool SafeInit<c_init_tag>::error_ = false;
template<> nlib_onceflag SafeInit<c_init_tag>::flag_ = NLIB_ONCE_INIT;
template<> void SafeInit<c_init_tag>::OnceFunc() {
bool err;
err = SafeInit<a_init_tag>::Init(); // 'c' depends 'a'.
if (err) {
error_ = true;
return;
}
nlib_printf("SafeInit<c_init_tag>::OnceFunc()\n");
}
template<> bool SafeInit<d_init_tag>::error_ = false;
template<> nlib_onceflag SafeInit<d_init_tag>::flag_ = NLIB_ONCE_INIT;
template<> void SafeInit<d_init_tag>::OnceFunc() {
bool err;
err = SafeInit<b_init_tag>::Init(); // 'd' depends 'b'.
if (err) {
error_ = true;
return;
}
err = SafeInit<c_init_tag>::Init(); // 'd' depends 'c'.
if (err) {
error_ = true;
return;
}
nlib_printf("SafeInit<d_init_tag>::OnceFunc()\n");
}
bool SafeInitDemo() {
bool err;
err = SafeInit<c_init_tag>::Init();
if (err) return false;
err = SafeInit<d_init_tag>::Init();
return !err;
}
static bool SampleMain(int, char**) { return SafeInitDemo(); }
NLIB_MAINFUNC