In a multi-threaded environment, sometimes we do not need to call a function multiple times or some variables are initialized multiple times. They only need to be called once or initialized once. Most of the time, we write the following code to initialize some data. This Code does not have any problems in a single thread, but is unpredictable in multithreading.
[Cpp] bool initialized = false; // global flag
If (! Initialized ){
// Initialize if not initialized yet
Initialize ();
Initialized = true;
}
Or
Static std: vector <std: string> staticData;
Void foo ()
{
If (staticData. empty ()){
StaticData = initializeStaticData ();
}
...
}
Bool initialized = false; // global flag
If (! Initialized ){
// Initialize if not initialized yet
Initialize ();
Initialized = true;
}
Or
Static std: vector <std: string> staticData;
Void foo ()
{
If (staticData. empty ()){
StaticData = initializeStaticData ();
}
...
}
To solve the data inconsistency problem caused by resource competition in the above multi-thread, most of our solutions are to use mutex locks for processing. The latest processing method is provided in C ++ 11: Use the std: call_once function for processing. The following header file is defined: # include <mutex>
[Cpp] template <class Function, class... Args>
Void call_once (std: once_flag & flag, Function & f, Args & args ...);
Parameter Parsing Parameters:
Flag-an object, for which exactly one function gets executed
F-function to be called
Args...-parameters passed to function f (multiple parameters are allowed)
The returned value is (none)
Throw an exception
Std: system_error if any condition prevents callto call_once from executing as specified any exception thrown by f
Template <class Function, class... Args>
Void call_once (std: once_flag & flag, Function & f, Args & args ...);
Parameter Parsing Parameters:
Flag-an object, for which exactly one function gets executed
F-function to be called
Args...-parameters passed to function f (multiple parameters are allowed)
The returned value is (none)
Throw an exception
Std: system_error if any condition prevents callto call_once from executing as specified any exception thrown by f
Example:
[Cpp] static std: vector <std: string> staticData;
Std: vector <std: string> initializeStaticData ()
{
Std: vector <std: string> vec;
Vec. push_back ("initialize ");
Return vec;
}
Void foo ()
{
Static std: once_flag oc;
Std: call_once (oc, [] {staticData = initializeStaticData ();});
}
Static std: vector <std: string> staticData;
Std: vector <std: string> initializeStaticData ()
{
Std: vector <std: string> vec;
Vec. push_back ("initialize ");
Return vec;
}
Void foo ()
{
Static std: once_flag oc;
Std: call_once (oc, [] {staticData = initializeStaticData ();});
} As shown in the preceding example, the first parameter of the call_once function is an object of std: once_flag. The second parameter can be a function, a member function, a function object, or a lambda function. In practice, we often use this function for Singleton Implementation of delayed initialization or classes ).
[Cpp] class X {
Private:
Mutable std: once_flag initDataFlag;
Void initData ()
{
_ Data = "init ";
}
Std: string _ data;
Public:
Std: string & getData (){
Std: call_once (initDataFlag, & X: initData, this );
Return _ data;
}
};
Class X {
Private:
Mutable std: once_flag initDataFlag;
Void initData ()
{
_ Data = "init ";
}
Std: string _ data;
Public:
Std: string & getData (){
Std: call_once (initDataFlag, & X: initData, this );
Return _ data;
}
};
Exception: All exceptions generated by the called function will be thrown again, so you 'd better handle the Exception. If the first call fails, the second call will continue, and so on until the call is successful.
About program Compilation: You need to add the-std = c ++ 0x or-std = c ++ 11 and-lpthread options