Таймер буста перестал работать из-за британского летнего времени - PullRequest
0 голосов
/ 28 марта 2011

Мы изменили время на этих выходных здесь, в Великобритании. С тех пор мой таймер буста перестал работать на моем ПК.

Вот что я должен сделать, если я хочу запустить 10-секундный таймер:

  boost::asio::io_service service;
  boost::asio::deadline_timer timer(service);

  boost::posix_time::ptime time = 
    boost::posix_time::microsec_clock::local_time();
  timer.expires_at(time + boost::posix_time::time_duration(0,0,10));

  timer.async_wait(boost::bind(&OnTimeOut, boost::asio::placeholders::error));
  service.run();

Теперь это не работает, я не ждал, но я ожидаю, что время ожидания истечет через час и 10 секунд. Чтобы доказать свою точку зрения, если я сделаю следующее, она истечет через 10 секунд:

  boost::asio::io_service service;
  boost::asio::deadline_timer timer(service);

  boost::posix_time::ptime time = 
    boost::posix_time::microsec_clock::local_time();
  timer.expires_at(time - boost::posix_time::time_duration(0,59,50));

  timer.async_wait(boost::bind(&OnTimeOut, boost::asio::placeholders::error));
  service.run();

Никто не знает, что я делаю неправильно, или, если есть что-то, что я должен сделать, чтобы избежать этой проблемы.

Ответы [ 3 ]

4 голосов
/ 29 марта 2011

Проблема, с которой вы столкнулись, вызвана таймером по умолчанию в asio, который использует часы boost.date_time, которые являются таймером настенных часов. Он представляет фактическое время, как показывают ваши настенные часы.

Если вы посмотрите на значение по умолчанию time_traits, используемое asio deadline_timer (boost/asio/time_traits.hpp), вы увидите, что его реализация now() использует boost::posix_time::microsec_clock::universal_time(). Это означает, что Asio понимает, сколько времени, UTC. Когда вы переходите в абсолютное время к expires_at(), asio сравнивает его с пониманием того, который час, то есть UTC.

Я полагаю, что использование local_time() сработало только по стечению обстоятельств, потому что оно совпадало с UTC.

Хотя, как уже указывалось, использование часов без летнего времени значительно улучшает ситуацию, фундаментальная проблема все еще существует.

UTC все еще не монотонные часы. У него будут високосные годы и високосные секунды, но в первую очередь пользователь (или, скорее всего, ntpd) может изменить часы компьютера, и ваши таймеры начнут выходить из строя.

Это гораздо более тонкий вопрос, который можно решить, определив свою собственную специализацию asio::time_traits, используя монотонные часы. Например, clock_gettime(CLOCK_MONOTONIC).

3 голосов
/ 28 марта 2011

Вы можете попробовать использовать expires_from_now вместо ручного добавления смещения к текущему времени.

2 голосов
/ 28 марта 2011

Моя лучшая ставка на то, что он перестает работать, состоит в том, что вы устанавливаете таймер с помощью local_time (), в то время как внутренности таймера используют время UTC, которое совпадает с британским "зимним" временем.Решение уже дано Space_C0wb0y

...