boost::thread on a functor

It is possible to create a boost::thread passing to its constructor a functor, in this way we could keep a state for our new thread as private data member of the class representing the functor.

Let's write an application where a couple of threads are create and loop using a private data member. It is worthy noting that since we are accessing a shared resource - the console, where we are printing some logging from our threads - we must use a mutex, to rule the access to it.

#include <iostream>
#include "boost/thread/thread.hpp"
#include "boost/thread/mutex.hpp"

using std::cout;
using std::endl;

namespace
{
class Count
{
static boost::mutex mio_; // 1.
int multi_;
public:
Count(int multi) : multi_(multi) { }

void operator()()
{
for (int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock lock(mio_); // 2.
cout << "Thread " << boost::this_thread::get_id() << " is looping: " << i*multi_ << endl;
}
}
};

boost::mutex Count::mio_; // 3.
}

void dd02()
{
cout << "Main thread " << boost::this_thread::get_id() << endl;
boost::thread t1(Count(1));
boost::thread t2(Count(-1));
t1.join();
t2.join();
cout << "Back to the main thread " << endl;
}

1. this mutex is an implementation detail of Count, it is unique in the class, permitting different threads to access the resource. That's way it is static private.
2. the mutex protect the access to the console, we use a scoped_lock, that means the lock is automatically released when the code reach the end of scope. In this way all threads have a fair chance to get access to the resource.
3. since the mutex is a static member of Count, we should remember to define it.

Actually, in such a simple case it is not worthy to create a class, a free function would be enough, expecially when we realize that we can pass to the thread constructor the parameters for the function - a clever trick from the designer of the thread class.

So, let's rewrite the example using just a free function:

#include <iostream>
#include "boost/thread/thread.hpp"
#include "boost/thread/mutex.hpp"

using namespace std;

namespace
{
boost::mutex mio;

void count(int multi)
{
for(int i = 0; i < 10; ++i)
{
boost::mutex::scoped_lock lock(mio);
cout << boost::this_thread::get_id() << ": " << multi * i << endl;
}
}
}

void dd03()
{
boost::thread t1(&count, 1);
boost::thread t2(&count, -1);

t1.join();
t2.join();
}

No comments:

Post a Comment