jogan
jogan

Reputation: 85

What is the most efficient way to calling a function every n seconds in c++?

So I'm trying to call a function every n seconds. The below is a simple representation of what I'm trying to achieve. I wanted to know if the below method is the only way to achieve this. I would love if the "if" condition can be avoided.

#include <stdio.h>
#include <time.h>

void print_hello(int i) {
  printf("hello\n");
  printf("%d\n", i);
}

int main () {
   time_t start_t, end_t;
   double diff_t;

   time(&start_t);

   int i = 0;

   while(1) {
     time(&end_t);
     // printf("here in main");

     i = i + 1;
     diff_t = difftime(end_t, start_t);
     if(diff_t==5) {
        // printf("Execution time = %f\n", diff_t);
        print_hello(i);
        time(&start_t);
     }
   }

   return(0);
}

Upvotes: 1

Views: 287

Answers (1)

Scheff&#39;s Cat
Scheff&#39;s Cat

Reputation: 20171

The usage of time in OPs program can be reduced to something like

// get tStart;
// set tEnd = tStart + x;
do {
  // get t;
} while (t < tEnd);

This is what is called busy-wait.

It might be used to write code with most precise timing as well as in other special cases. The draw-back is that the waiting consumes ful CPU load. (You might be even able to hear this – by raising ventilation noise.)

In general, however, spinning is considered an anti-pattern and should be avoided, as processor time that could be used to execute a different task is instead wasted on useless activity.

Another option is to delegate the wake-up to the system, which reduces the load of process/thread to minimum while waiting:

#include <chrono>
#include <iostream>
#include <thread>

void print_hello(int i)
{
  std::cout << "hello\n"
    << i << '\n';
}

int main ()
{
  using namespace std::chrono_literals; // to support e.g. 5s for 5 sceconds

  auto tStart = std::chrono::system_clock::now();
  for (int i = 1; i <= 3; ++i) {
    auto tEnd = tStart + 2s;
    std::this_thread::sleep_until(tEnd);
    print_hello(i);
    tStart = tEnd;
  }
}

Output:

hello
1
hello
2
hello
3

Live Demo on coliru

(I had to reduce number of iterations and the waiting times to prevent the TLE in online compiler.)

std::this_thread::sleep_until

Blocks the execution of the current thread until specified sleep_time has been reached.

The clock tied to sleep_time is used, which means that adjustments of the clock are taken into account. Thus, the duration of the block might, but might not, be less or more than sleep_time - Clock::now() at the time of the call, depending on the direction of the adjustment. The function also may block for longer than until after sleep_time has been reached due to scheduling or resource contention delays.

The last sentence mentions the draw-back of this solution: The OS may decide to wake-up the thread/process later than requested. That may happen e.g. is OS is under high load. In the “normal” case, the latency shouldn't be more than a few milli-seconds. So, the latency might be tolerable.

Please, note how tEnd and tStart are updated in loop. The current wake-up time is not considered to prevent accumulation of latencies.

Upvotes: 4

Related Questions