12.4. Initializing Shared Resources Once
Problem
You have a number of threads that are using a resource that must only be initialized once.
Solution
Either initialize the resource before the threads are started, or if you can’t, use
the call_once function defined in <boost/thread/once.hpp> and the type once_flag. Example
12-5 shows how to use call_once.
Example 12-5. Initializing something once
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
// Some sort of connection class that should only be 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; // You probably don't want to use a global, so see the
// next Recipe
int main() {
boost::thread_group grp;
for (int i = 0; i < 100; ++i)
grp.create_thread(worker);
grp.join_all();
std::cout << c.i_ << '\n'; // c.i_ = 1
}Discussion
A shared resource has to be initialized somewhere, and you may want the first thread
to use it to do the initializing. A variable of type once_flag (whose exact type is platform-dependent) and the call_once function can keep multiple threads from
re-initializing the same object. You have to do two things.
First, initialize your once_flag
variable to the macro BOOST_ONCE_INIT
. This is a platform-dependent value. In Example 12-5, the class Conn represents some sort ...