Getting Started with Boost Threads

Boost is collection of open source C++ libraries. They are released under the “Boost License” so they can be incorporated into open-source and closed-source projects. Anyway, one of the libraries in the collection that is of particular interest to me is the threading library. It’s cross-platform, so I should be able to run my code on any platform. It also uses proper C++ templating, so it’s clean as well.

This post is targeted to readers who already have some experience writing multi-threaded applications (in Java for example). This post tell you only what you need to go from nothing to compiling a simple Boost-based program that uses locks.

The first thing we have to do is get Boost. The threading library was last changed in version 1.36, so anything 1.36 and later will do. You can do a manual install by following the instructions in the Getting Started Guide. However, I use Ubuntu 9.04 which packages the Boost library, and I’m a huge advocate of using your distro’s package management system so I’ll be using that.

To get Boost in Ubuntu, run the following:

sudo apt-get install libboost1.37-dev
echo "That was easy!"

So now all that’s left is make a simple, multi-threaded application.

// File: sample.cpp
#include <iostream>
#include <boost/thread.hpp>

using namespace std;


class MyRunnable
{
public:

	MyRunnable(int id, boost::mutex* mutex, boost::barrier* bar)
	{
		this->id    = id;
		this->mutex = mutex;
		this->bar   = bar;
	}

	// The entry point for a thread
	void operator()()
	{
		for(int i = 0; i < 10; ++i)
		{
			boost::mutex::scoped_lock  lock(*mutex);					
                       cout << "id: " << this->id << ", " << i << endl;	
		}

		// all done, wait at the barrier. 
                // wait() returns when everyone has met at the barrier
		bar->wait();
	}

private:
	int id;
	boost::mutex* mutex;
	boost::barrier* bar;
	
};

int main()
{
	boost::mutex io_mutex;
        // this barrier will wait for two invocations of wait()
	boost::barrier my_barrier(2); 

	cout << "Starting two counting threads..." << endl;
	// the boost::mutex cannot be copied (for obvious reasons)
	// so we must pass the pointer to the mutex.
	boost::thread thread1(MyRunnable(1, &io_mutex, &my_barrier));
	boost::thread thread2(MyRunnable(2, &io_mutex, &my_barrier));

	thread1.join(); // wait for thread1 to finish

	// Note how the program doesn't return until all threads are dead
	return 0;
	
}

Then compile and run!:

g++ sample.cpp -lboost_thread-mt
./a.out

The output will of course vary a lot each time you run it, but it should look something like this:

id: Starting two counting threads...
1, 0
id: 1, 1
id: 1, 2
id: 1, 3
id: 1, 4
id: 1, 5
id: 1, 6
id: 1, 7
id: 1, 8
id: 1, 9
id: 2, 0
id: 2, 1
id: 2, 2
id: 2, 3
id: 2, 4
id: 2, 5
id: 2, 6
id: 2, 7
id: 2, 8
id: 2, 9

Notice how the output of the two threads we created is interleaved with the output of the main thread of execution. This is one of the dangers of threading!

2 comments

  1. Pingback: Development Ideas

Leave a Comment