Reputation: 123139
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.
Upvotes: 1
Views: 743
Reputation: 376
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.
Upvotes: 3