There is another problem that is not resolved: How to make initialization work (such as constructors) thread-safe. For example, if a reference program is to produce a unique global object, a function is invoked to return a static object because of the instantiation order, and it must ensure that the static object is generated the first time it is called. The problem here is that if multiple threads call this function at the same time, then the constructor of the static object is called multiple times, so the error occurs. The solution to this problem is the so-called "one time implementation" (once routine). "Once implementation" can only be performed once in an application. If multiple threads want to perform this operation at the same time, there is only one real execution, and the other thread must wait for the operation to end. To ensure that it is only executed once, this routine is called indirectly by another function, and this function passes it a pointer and a special flag that indicates whether the routine has been invoked. This flag is initialized in a static manner, which ensures that it is initialized during compilation rather than runtime. So there is no problem with multiple threads initializing it at the same time. The Boost line threading provides boost::call_once to support "one implementation" and defines a flag Boost::once_flag and a macro boost_once_init that initializes the flag. List6 is an example of using Boost::call_once. It defines a static global integer with an initial value of 0 and a static Boost::once_flag instance initialized by Boost_once_init. The main function creates two threads, all of which want to initialize the global integer by passing in a function call Boost::call_once, which adds 1 to it. The main function waits for two threads to end and outputs the final result to Std::cout. The final result shows that the operation was actually executed only once, because its value is 1.
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
#include <iostream>
int i = 0;
Boost::once_flag flag =
boost_once_init;
void init ()
{
++i;
}
void thread ()
{
boost::call_once (&init, flag);
}
int main (int argc, char* argv[])
{
boost::thread thrd1 (&thread);
Boost::thread Thrd2 (&thread);
Thrd1.join ();
Thrd2.join ();
Std::cout << i << Std::endl;
return 0;
}
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
//Some sort of connection class that should is only initialized once struct Conn
{
static void init () {++i_ ;}
Static Boost::once_flag Init_;
static int i_;
// ...
};
int conn::i_ = 0;
Boost::once_flag conn::init_ = boost_once_init;
void Worker () {
boost::call_once (conn::init, conn::init_);
Do the real work ...
}
Conn C; Probably don ' t want to use a global, so the
//next Recipe
int main () {
Boost::thread_group grp ;
for (int i = 0; i < ++i)
Grp.create_thread (worker);
Grp.join_all ();
Std::cout << c.i_ << ' \ n ';//c.i_ = 1
}
A shared resource has to be initialized somewhere, and you want to use the resource's thread for the first time to complete the initialization work. A once_flag type and call_once function can ensure that multiple threads do not initialize the same object repeatedly. First, you must use the Boost_once_init macro to initialize the Once_flag object. Boost::once_flag conn::init_ = Boost_once_init; Then call the Call_once function, Boost::call_once (Conn::init, conn::init_); The first parameter is the address of the initialization function that you want to be executed once.