We changed time this weekend here in the UK. Since then my boost timer have stopped working on my PC.
Here is what I should do if I want to run a 10 second timer:
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();
Now it does not work, I did not wait but I expect it to time out in one hour and 10 seconds. To prove my point, if I do the following, it will time out in 10 seconds:
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();
Anybody no wh开发者_运维技巧at I am doing wrong, or if there is something I should do to avoid this issue.
The problem you're experiencing is caused by the default timer in asio, which uses boost.date_time's clock, which is a wall clock timer. It represents the actual time as your wall clock would show.
If you look at the default time_traits
used by the asio deadline_timer (boost/asio/time_traits.hpp
) you'll see that its implementation of now()
uses boost::posix_time::microsec_clock::universal_time()
. This means that asio's understanding of what time it is, is UTC. When you pass in an absolute time to expires_at()
, asio will compare it to its understanding of what time it is, which is UTC.
I believe that your use of local_time()
only worked by coincidence, because it happened to be the same as UTC.
Although, as pointed out already, using a clock that doesn't have daylight savings significantly improves the situation, the fundamental problem still exists.
UTC is still not a monotonic clock. It will have leap years and leap seconds, but primarily, the user (or ntpd more likely) can change the computer's clock, and your timers will start to fail.
This is a much more subtle issue that can be solved by defining your own asio::time_traits
specialization, using a monotonic clock. Such as clock_gettime(CLOCK_MONOTONIC)
for instance.
You could try using expires_from_now
, instead of manually adding an offset to the current time.
My best bet why it stops working is that you set up a timer with local_time() while the internals of the timer use UTC time, which happens to be the same as British "winter" time. The solution is already given by Space_C0wb0y
精彩评论