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 ...

Get C++ Cookbook now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.