通过引用传递bool并使用其最新值

时间:2013-12-03 21:36:53

标签: c++ boost thread-synchronization

我有以下代码:

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 变量可以用作标志,但我错了或者我做错了。

2 个答案:

答案 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::refthread除外)是您将 引用传递给临时

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();
}

请注意