Почему 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() Функциональные блоки всего на несколько часов определяются смещением часового пояса вашего компьютера, а не навсегда.

Другие вопросы по тегам