Boost libraries (Boost.Thread) provide an easy implementation for multi-threading applications in C++.
Code is portable on different OS platforms. Three basic code examples are discussed below for a kick start on use of these libraries.
Last example also shows the use of mutex.
On Linux, it uses pthreads underlying. So it can be thought of pthreads wrapped in C++ style objects. BOOST library provides different ways to use locks also.

Here is the official link:-
http://www.boost.org/doc/libs/1_49_0/doc/html/thread.html

Example-1 : Basic Multi-threading

This simple example spawns two threads. Callback function for each thread is invoked.

#include <boost/thread.hpp>
void readerApi()
{
  for (int i=0; i < 10; i++) {
    usleep(400);
    std::cout << "readerApi: " << i
              << std::endl;
  }
}
void writerApi()
{
  for (int i=0; i < 10; i++) {
    std::cout << "writerApi: " << i
              << std::endl;
    usleep(400);
  }
}

int main()
{
  boost::thread readerThread(readerApi);
  boost::thread writerThread(writerApi);

  readerThread.join();
  writerThread.join();
}

Compile and output:

$ g++ -o b1 boost1.cpp -lboost_thread
$ ./b1
writerApi: 0
readerApi: 0
writerApi: 1
readerApi: 1
writerApi: 2
readerApi: 2
writerApi: 3
writerApi: 4
readerApi: 3
writerApi: 5
readerApi: 4
writerApi: 6
readerApi: 5
writerApi: 7
readerApi: 6
writerApi: 8
readerApi: 7
writerApi: 9
readerApi: 8
readerApi: 9

Example-2 : Thread Callbacks with parameters

In this example a parameter, pointer to shared variable is passed to the callback.
Writer callback modifies the variable at regular intervals.
Reader callback dumps the value, writer callback modifies the value.

#include <boost/thread.hpp>

void readerApi(int* readVar)
{
  for (int i=0; i < 10; i++) {
    usleep(400);
    std::cout << "readerApi: " << *readVar
              << std::endl;
  }
}
void writerApi(int* writeVar)
{
  for (int i=0; i < 10; i++) {
    std::cout << "writerApi: " << *writeVar
              << std::endl;
    usleep(400);
    *writeVar = (*writeVar)++;
  }
}

int main()
{
  int variable = 100;
  boost::thread readerThread(readerApi, &variable);
  boost::thread writerThread(writerApi, &variable);

  readerThread.join();
  writerThread.join();
}

Compile and output:

$ g++ -o b2 boost2.cpp -lboost_thread
$ ./b2
writerApi: 100
readerApi: 100
writerApi: 101
readerApi: 101
writerApi: 102
readerApi: 102
writerApi: 103
readerApi: 103
writerApi: 104
readerApi: 104
writerApi: 105
readerApi: 105
writerApi: 106
readerApi: 106
writerApi: 107
readerApi: 107
writerApi: 108
readerApi: 108
writerApi: 109
readerApi: 109

Example-3 : Classes for callback. Usage of Mutexes

Instead of using callback functions, we use an object.
Object should be ‘callable‘, means have operator () overloaded within the class.
Writer takes a lock before modifying the shared variable. And then update global variable with this variable.
Reader accesses the global variable for its use.

#include <boost/thread.hpp>

int globalVariable;

class Reader
{
  public:
    Reader(int waitTime) { _waitTime = waitTime;}
    void operator() () {
      for (int i=0; i < 10; i++) {
        std::cout << "Reader Api: " << globalVariable << std::endl;
        usleep(_waitTime);
      }
      return;
    }
  private:
    int _waitTime;
};

class Writer
{
  public:
    Writer(int variable, int waitTime)
    {
      _writerVariable = variable;
      _waitTime = waitTime;
    }
    void operator () () {
      for (int i=0; i < 10; i++) {
        usleep(_waitTime);
        // Take lock and modify the global variable
        boost::mutex::scoped_lock lock(_writerMutex);
        globalVariable = _writerVariable;
        _writerVariable++;
        // since we have used scoped lock,
        // it automatically unlocks on going out of scope
      }
    }
  private:
    int _writerVariable;
    int _waitTime;
    static boost::mutex _writerMutex;
};

boost::mutex
Writer::_writerMutex;

int main()
{
  Reader reads(100);
  Writer writes1(100, 200);
  Writer writes2(200, 200);

  boost::thread readerThread(reads);
  boost::thread writerThread1(writes1);
  usleep(100);
  boost::thread writerThread2(writes2);

  readerThread.join();
  writerThread1.join();
  writerThread2.join();
}

Compile and output: (Output will be different in different runs as the order of updation may vary)

$ g++ -o b3 boost3.cpp -lboost_thread
$ ./b3
Reader Api: 0
Reader Api: 200
Reader Api: 103
Reader Api: 104
Reader Api: 106
Reader Api: 107
Reader Api: 109
Reader Api: 209
Reader Api: 209
Reader Api: 209
Tagged with →  
Share →

20 Responses to BOOST multi-threading for C++

  1. Harwinder says:

    Good Article. This article can serve as a primer for anyone looking to do multi-threading work with Boost.Thread library, which I find the simplest library to multi-threaded library to use. Very useful !!!

  2. Sandeep Thakur says:

    Awesome Post!!!

  3. Max says:

    Wonder if in the example 3, Reader class, there was some intent to use _waitTime member?
    Also there, I am not quite sure that private _writerMutex could be initialized just like that…

    • Intent in using _waitTime is to delay the read, write a bit, so that the example becomes clear in terms of steps performed.
      Regarding mutex, I do not see any issues, please point out specifically, I will humbly correct it.

  4. Max says:

    In somewhat similar wake – why do we need this in main():
    int variable = 100;
    ?
    I was wrong about private static boost::mutex _writerMutex; initialization – it is allowed.

  5. nerd says:

    Hi Ashish,
    In example 1,when printing on console,context switch might happen resulting in haphazard view on console . We can do following to overcome this :-

    1)Just use a simple mutex within each thread. The mutex is shared by all threads.
    2)Send all the output to a single thread that does nothing but the logging.
    3) Send all the output to a separate logging application.

  6. nerd says:

    “Object should be ‘callable‘, means have operator () overloaded within the class.”

    This is also known as function object(functor) .

  7. nerd says:

    Also to achieve functionality of callbacks,boost::future and boost::promises are handy stuff.

    void callfunc(future f) {
    std::cout << "Future is ready with value = " << f.get() << "\n";
    }

    void f9() {
    promise pi;
    future f(pi);
    boost::callback_reference cb_ref1 = f.add_callback(boost::bind(callfunc, f));
    pi.set(33); // my callback will print “Future is ready” now
    }

  8. Humor News says:

    Wow Excellent blog!

  9. Free Movies says:

    Wow Excellent blog!

  10. Avinash says:

    Hi Ashish,

    Can you please suggest a Linux OS which I can use to learn C++. I am currently using Maveric OSX. I am running into issues while trying to integrate BOOST libraries.

    Regards,
    Avinash

  11. Feng says:

    Thanks much for the post! I have a simple question: why _writerMutex is defined as static variable?

  12. mohamed says:

    hello

    i would thanks for this objective tutorial that make a lot of thing easy for me about thread’s techniques.

    i have a simple issue, that the usleep function doesn’t work for me.

    the complier tell me that this function is undefined.

    what shall i do ?

    thanks again

  13. Visweswaran says:

    I’ve been looking for this. Thank you

  14. Swanand says:

    @mohamed
    To resolve usleep() related error, use following:
    1. Add #include
    2. boost::this_thread::sleep(boost::posix_time::milliseconds(100)); //thread will sleep for 100ms.

    Regards,
    Swanand

Leave a Reply

Your email address will not be published. Required fields are marked *