简体   繁体   中英

Why does boost::timed_wait block forever when called with absolute time?

I am trying to understand how to use timed_wait . I found only few examples ( here and here ) and I have a problem when calling it with an absolute time. The following code is a simplified example, in reality this all happens inside a class, so I thought it would be easier to check my predicate manually instead of having to use some binding and pass it to 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));
}

The first version blocks forever and I dont understand why. On the other hand, the second version afaik is subject to spurious wakeups. As I said before, in the real code, all this is place inside a class, so to use the overload that takes a predicate I would have to do something like

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

but then I am not 100% sure if a spurious wakeup will make timed_wait return true (if this is the case my while (x > local_time()) would be superfluous.

Use boost::get_system_time() + dt , which is UTC-based, instead of local_time() + dt , which is timezone-adjusted, because wait_lock(...) uses boost::get_system_time() to compare current time with the target absolute time.

The following example illustrates the problem:

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

Output:

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

So, your absolute time-based wait() function blocks just for a few hours specified by timezone offset of your computer, not forever.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM