This sample shows how to safely and efficiently run initialization in multiple threads.
It uses nlib_once
to write the dependencies between the initialization processes, and runs once when each initialization process is needed.
The procedure is as follows.
-
Define tag types for each initialization process. In this sample, these tag types are
a_init_tag
through d_init_tag
.
-
Use the tags to code the definitions for
m_Flag
and m_Error
for each instantiation of the SafeInit
class template.
-
Use the tags to implement the
OnceFunc
function for each instantiation of the SafeInit
class template.
-
The initialization process can be run with
SafeInit<tag type>::Init
.
The dependencies for the initialization sequence are described in the OnceFunc
function called through nlib_once
. By using nlib_once
, the initialization function calls do not collide, even if initialization processes are run on multiple threads.
In the sample, the dependencies are written as a->b, a->c, b->d, c->d.
template<class TAG, class ERRORTYPE = bool>
class SafeInit {
public:
typedef ERRORTYPE ErrorType;
typedef TAG TagType;
static const ErrorType& Init() {
return m_Error;
}
private:
static ErrorType m_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>::m_Error = false;
template<> void SafeInit<a_init_tag>::OnceFunc() {
}
template<> bool SafeInit<b_init_tag>::m_Error = false;
template<> void SafeInit<b_init_tag>::OnceFunc() {
bool err;
err = SafeInit<a_init_tag>::Init();
if (err) {
m_Error = true;
return;
}
}
template<> bool SafeInit<c_init_tag>::m_Error = false;
template<> void SafeInit<c_init_tag>::OnceFunc() {
bool err;
err = SafeInit<a_init_tag>::Init();
if (err) {
m_Error = true;
return;
}
}
template<> bool SafeInit<d_init_tag>::m_Error = false;
template<> void SafeInit<d_init_tag>::OnceFunc() {
bool err;
err = SafeInit<b_init_tag>::Init();
if (err) {
m_Error = true;
return;
}
err = SafeInit<c_init_tag>::Init();
if (err) {
m_Error = true;
return;
}
}
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