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