skip to Main Content

What is the best way in C++11 to implement a high-resolution timer that continuously checks for time in a loop, and executes some code after it passes a certain point in time? e.g. check what time it is in a loop from 9am onwards and execute some code exactly at 11am. I require the timing to be precise (i.e. no more than 1 microsecond after 9am).

I will be implementing this program on Linux CentOS 7.3, and have no issues with dedicating CPU resources to execute this task.

3

Answers


  1. Instead of implementing this manually, you could use e.g. a systemd.timer. Make sure to specify the desired accuracy which can apparently be as precise as 1us.

    Login or Signup to reply.
  2. My suggestion would be to use timer_create(). This allows you to get notified by a signal at a given time. You can then implement your action in the signal handler.

    In any case you should be aware that the accuracy of course depends on the system clock accuracy.

    Login or Signup to reply.
  3. a high-resolution timer that continuously checks for time in a loop,

    First of all, you do not want to continuously check the time in a loop; that’s extremely inefficient and simply unnecessary.

    …executes some code after it passes a certain point in time?

    Ok so you want to run some code at a given time in the future, as accurately as possible.

    The simplest way is to simply start a background thread, compute how long until the target time (in the desired resolution) and then put the thread to sleep for that time period. When your thread wakes up, it executes the actual task. This should be accurate enough for the vast majority of needs.

    The std::chrono library provides calls which make this easy:

    Here’s a snippet of code which does what you want using the system clock (which makes it easier to set a wall clock time):

    // c++ --std=c++11 ans.cpp -o ans
    
    #include <thread>
    #include <iostream>
    #include <iomanip>
    
    // do some busy work
    int work(int count)
    {
        int sum = 0;
        for (unsigned i = 0; i < count; i++)
        {
            sum += i;
        }    
        return sum;
    }
    
    std::chrono::system_clock::time_point make_scheduled_time (int yyyy, int mm, int dd, int HH, int MM, int SS)
    {
        tm datetime = tm{};
    
        datetime.tm_year = yyyy - 1900; // Year since 1900
        datetime.tm_mon = mm - 1; // Month since January
        datetime.tm_mday = dd; // Day of the month [1-31]
        datetime.tm_hour = HH; // Hour of the day [00-23]
        datetime.tm_min = MM;
        datetime.tm_sec = SS;
    
        time_t ttime_t = mktime(&datetime);
    
        std::chrono::system_clock::time_point scheduled = std::chrono::system_clock::from_time_t(ttime_t);
    
        return scheduled;
    }
    
    void do_work_at_scheduled_time()
    {
        using period = std::chrono::system_clock::period;
    
        auto sched_start = make_scheduled_time(2019, 9, 17,  // date
                                               00, 14, 00);  // time
    
        // Wait until the scheduled time to actually do the work
        std::this_thread::sleep_until(sched_start);
    
        // Figoure out how close to scheduled time we actually awoke
        auto actual_start = std::chrono::system_clock::now();
        auto start_delta = actual_start - sched_start;
        float delta_ms = float(start_delta.count())*period::num/period::den * 1e3f;
    
        std::cout << "worker: awoken within " << delta_ms << " ms" << std::endl;
    
        // Now do some actual work!
        int sum = work(12345);
    }
    
    int main()
    {
        std::thread worker(do_work_at_scheduled_time);
    
        worker.join();
    
        return 0;
    }
    

    On my laptop, the typical latency is about 2-3ms. If you use the high_resolution_clock you should be able to get even better results.

    There are other APIs you could use too, such as Boost where you could use ASIO to implement high res timeout.

    I require the timing to be precise (i.e. no more than 1 microsecond after 9am).

    Do you really need it to be accurate to the microsecond? Consider that at this resolution, you will also need to take into account all sorts of other factors, including system load, latency, clock jitter, and so on. Your code can start to execute at close to that time, but that’s only part of the problem.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search