By reference to boost::thread

The boost::thread constructor expects a callable object as parameter, and it expects it to be passed by value. Actually it makes sense. Since we have to work with that object in a different thread it is safer to having an independent copy of it.

But if the caller accept to take the responsibility of guaranteeing that object is going to be valid during all the existence of the newly created thread, there should be a way to pass that object by reference. And actually there is, and it requires us wrapping the object by calling std::ref (or boost::ref, if this new C++0x standard wrapper is not available yet for your compiler).

I have already done some testing on std::ref and boost::thread for Windows/VC++, here I replied the test - with a few variations - for Linux/g++.

This time I can't proudly say that the original code worked with no change whatsoever on the new platform, and this is due to the fact that std::ref is in the std::tr1 namespace, in the current GNU implementation. So, for the time being, it would probably be better using boost::ref() instead.

In any case, here is the include section I used for this version:

#include <iostream>
#include <tr1/functional>
#include <boost/thread.hpp>

Then I created a functor that performs a countdown:

namespace
{
class Callable
{
private:
static boost::mutex mio_;
int value_;
public:
explicit Callable(int value) : value_(value) {}

int getValue() { return value_; }

void operator()()
{
while(value_ > 0)
{
boost::this_thread::sleep(boost::posix_time::seconds(1));

{
boost::lock_guard<boost::mutex> lock(mio_);
std::cout << value_-- << ' ';
std::cout.flush();
}
}
}
};

boost::mutex Callable::mio_;
}

Finally I wrote a function that uses two objects of this class:

void mt04()
{
Callable c1(5);
Callable c2(5);

boost::thread t1(c1); // 1.
boost::thread t2(std::tr1::ref(c2)); // 2.

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

std::cout << std::endl << "c1: " << c1.getValue()
<< ", c2: " << c2.getValue() << std::endl;
}

1. The thread t1 creates a copy of c1, and performs the countdown on its local copy. The original object c1 won't be changed.
2. The thread t1 is getting a reference to c2, so the countdown is actually changing the original object.

No comments:

Post a Comment