Почему boost::timed_wait блокируется навсегда, когда вызывается с абсолютным временем?
Я пытаюсь понять, как использовать timed_wait
, Я нашел только несколько примеров ( здесь и здесь), и у меня есть проблема при вызове с абсолютным временем. Следующий код является упрощенным примером, в действительности все это происходит внутри класса, поэтому я подумал, что будет проще проверить мой предикат вручную, вместо того, чтобы использовать какое-либо связывание и передавать его 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 ответ
Использование 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()
Функциональные блоки всего на несколько часов определяются смещением часового пояса вашего компьютера, а не навсегда.