Boost logo

Boost Users :

Subject: [Boost-users] boost::asio::deadline_timer precision issues
From: Warren Seine (warren.seine_at_[hidden])
Date: 2010-03-01 10:20:54


Hi,

I'm writing a timer class which calls a function every n ms. I'm using
Boost.Asio to achieve that. Please tell me if there is a better
solution. The usual pattern with boost::asio::deadline_timer is to call
`expires_from_now()' and `async_wait()' every time the timer expires.

The solution works, however the timer seems to have (important)
precision issues, as described in the sample code below. A simple
counter is incremented every 20 ms, and is displayed (and reset) every
1000 ms. The value displayed should therefore be close to 50. In
practice, it's closer to 40, which in unexplainable with such a simple
piece of code.

$ cat test.cc
#include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>

static boost::asio::io_service* s_service = 0;
static unsigned int s_counter = 0;

struct timer
{
   timer(unsigned int delay, boost::function< void () > callback) :
     m_timer(*s_service),
     m_callback(callback),
     m_delay(delay)
   {
   }

   void start()
   {
     m_timer.expires_from_now(boost::posix_time::millisec(m_delay));
     m_timer.async_wait(boost::bind(&timer::handle_wait, this, _1));
   }

   void handle_wait(const boost::system::error_code& e)
   {
     start();
     m_callback();
   }

   boost::asio::deadline_timer m_timer;
   boost::function< void () > m_callback;
   unsigned int m_delay;
};

void increment()
{
   s_counter++;
}

void display()
{
   std::cout << s_counter << std::endl;
   s_counter = 0;
}

int main()
{
   boost::asio::io_service service;
   s_service = &service;

   // Display the counter every 1000ms.
   timer t1(1000, display);
   // Increment the counter every 20ms.
   timer t2(20, increment);

   t1.start();
   t2.start();

   service.run();
}

$ g++ test.cc -o test -lboost_system
$ ./test
41
42
43
40
42
43
42
^C

My environment is GNU/Linux within a VM. My compiler is GCC 4.4 and I'm
linking with Boost 1.42. Please ask me any detail that might be relevant.

If that's an expected behavior, is there any way I can "trust" the
timer? I couldn't find any documentation discussing the issue.

Thanks,

-- 
Warren Seine

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net