我有以下代码:
MyClass::aMethod()
{
...
bool isStarted = false;
boost::thread(boost::bind(&MyClass::CheckTimeoutThread, this, isStarted));
...//some time later
isStarted = true;
...
}
MyClass::checkTimeoutThread(bool &isStarted)
{
...//some code here
while(anotherFlag)
{
...//do something
if(isStarted)//ALWAYS THE INITIAL VALUE OF FALSE
{
}
...
}
}
我预计 isStarted 变量可以用作标志,但我错了或者我做错了。
答案 0 :(得分:3)
boost::thread
将存储其参数的副本。但您可以在reference_wrapper
的帮助下传递boost::ref
来模拟参考。另请注意,您无需致电boost::bind
:
boost::thread t(&MyClass::CheckTimeoutThread, this, boost::ref(isStarted));
但请注意,您现在在isStarted
上有竞赛条件。您需要使用互斥锁同步访问它,或者使用原子类型(如果您的平台上有)(如果您有C ++ 11,那么您可以使用std::atomic<bool>
,如@PeteBecker所建议的那样。 )
修改显然,上述所有内容都假定isStated
至少与使用它的thread
一样长。实际上,这意味着线程必须在aMethod
返回时完成。或者,您可以将isStarted
设为数据成员。但是你仍然必须确保在MyClass
析构函数破坏之前加入线程。
答案 1 :(得分:1)
传递std::ref
的引用所需的最大问题(boost::ref
或thread
除外)是您将 引用传递给临时 强>
MyClass::aMethod()
{
...
bool isStarted = false;
}
/// Oops at the end of the method, `isStarted` no longer lives
在控件离开aMethod
后,通过陈旧参考的任何访问都是未定义的行为
我建议使用正确的同步: See it Live on Coliru
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
struct X
{
std::condition_variable cv;
std::mutex mx;
bool isStarted;
std::thread worker;
X() : isStarted(false) {}
void aMethod()
{
worker = std::thread(&X::Worker, this);
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::cout << "signalling worker\n";
std::unique_lock<std::mutex> lock(mx);
isStarted = true;
cv.notify_one();
}
worker.join();
isStarted = false;
}
void Worker()
{
std::unique_lock<std::mutex> lock(mx);
std::cout << "worker ready\n";
cv.wait(lock, [this] { return isStarted; });
std::cout << "worker started\n";
std::cout << "worker done\n";
}
};
int main()
{
X o;
o.aMethod();
}
请注意
s/std/boost
你应该可以在C ++ 03编译器上使用它isStarted
了。我添加它是因为虚假的唤醒:Why does pthread_cond_wait have spurious wakeups?