为什么在使用绝对时间调用时,boost :: timed_wait会永久阻塞?

时间:2017-06-07 08:17:47

标签: c++ boost condition-variable

我想了解如何使用timed_wait。我发现只有几个例子(herehere),并且在用绝对时间调用它时遇到问题。下面的代码是一个简化的例子,实际上这一切都发生在一个类中,所以我认为手动检查我的谓词更容易,而不必使用一些绑定并将其传递给timed_wait

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread.hpp>
#include <iostream>

bool done = false;
boost::mutex mutex;
boost::thread waitingThread;
boost::condition_variable cond;

void wait(boost::posix_time::time_duration dt){
    boost::mutex::scoped_lock lock(mutex);
    boost::system_time x = boost::posix_time::microsec_clock::local_time() + dt;
    bool timedOut = false;
    while((done == false) && (x > boost::posix_time::microsec_clock::local_time())) {
        timedOut = ! cond.timed_wait(lock,x);
    }
    if (timedOut){ std::cout << "timeout\n"; }
    else         { std::cout << "success\n"; }
}

void wait2(boost::posix_time::time_duration dt){
    boost::mutex::scoped_lock lock(mutex);
    bool timedOut = ! cond.timed_wait(lock,dt);
    if (timedOut){ std::cout << "timeout\n"; }
    else         { std::cout << "success\n"; }

}

void test(){
    //boost::thread waiter = boost::thread(wait,boost::posix_time::milliseconds(50));
    boost::thread waiter = boost::thread(wait2,boost::posix_time::milliseconds(50));
    boost::this_thread::sleep(boost::posix_time::milliseconds(2000));
}

第一个版本永远封锁,我不明白为什么。另一方面,第二版afaik受到虚假的唤醒。正如我之前所说,在实际代码中,所有这些都放在一个类中,所以要使用带谓词的重载,我必须做类似的事情

cond.timed_wait(lock,dt, ?bind?(&Foo::isDone,this));

但是我不能100%确定虚假的唤醒是否会使timed_wait返回true(如果是这种情况,我的while (x > local_time())将是多余的。

1 个答案:

答案 0 :(得分:3)

使用boost::get_system_time() + dt,这是基于UTC的,而不是local_time() + dt,这是时区调整的,因为wait_lock(...)使用boost::get_system_time()将当前时间与目标绝对值进行比较时间。

以下示例说明了问题:

int main() {
    std::cout << "System time: " 
              << boost::get_system_time() << std::endl;
    std::cout << "Local time: " 
              << boost::posix_time::microsec_clock::local_time() << std::endl;
}

输出:

System time: 2017-Jun-07 08:47:58.836677
Local time: 2017-Jun-07 11:47:58.837003

因此,您的绝对基于时间的wait()函数会阻止计算机的时区偏移指定的几个小时,而不是永久。