Execut1ve
Execut1ve

Reputation: 321

need to call a function at periodic time intervals in c++

I am writing a program in c++ where I need to call a function at periodic time intervals, say every 10ms or so. I've never done anything related to time or clocks in c++, is this a quick and easy problem or one of those where there is no neat solution?

Thanks!

Upvotes: 32

Views: 69411

Answers (9)

AlgebraicsAnonymous
AlgebraicsAnonymous

Reputation: 191

Assuming that getting the time point also take some time, the following code (which I have written without any fancy-schmancy shenanigans) is a bit more accurate:

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

void func() {
    std::cout << "This function does something!" << std::endl;
}

int main() {
    std::chrono::seconds one_sec(1);
    std::chrono::time_point starting_time = std::chrono::steady_clock::now();
    while(true) {
        std::this_thread::sleep_until(starting_time + one_sec);
        func();
        starting_time += one_sec;
    }
}

Of course, you can also put everything into a thread:

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

void func() {
    std::cout << "This function does something!" << std::endl;
}

void threadfunc() {
    std::chrono::seconds one_sec(1);
    std::chrono::time_point starting_time = std::chrono::steady_clock::now();
    while(true) {
        std::this_thread::sleep_until(starting_time + one_sec);
        func();
        starting_time += one_sec;
    }
}

int main() {
    std::thread periodicFunctionThread(threadfunc);
    periodicFunctionThread.join(); //Probably you would use detach, this is only for demonstration purposes.
}

Upvotes: 0

uIM7AI9S
uIM7AI9S

Reputation: 389

I made myself an async system. It should not be confused with std::async. Since it is custom made, I have full control over the timeline, so I can add, edit, remove, append, etc tasks. Mainly it runs in a single thread and guarantees safety between context switches, but also has support for multi-thread syncing. Try to make your own async system, from my experience I would say it's worth it

Upvotes: 0

florgeng
florgeng

Reputation: 886

To complete the question, the code from @user534498 can be easily adapted to have the periodic tick interval. It's just needed to determinate the next start time point at the beginning of the timer thread loop and sleep_until that time point after executing the function.

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

void timer_start(std::function<void(void)> func, unsigned int interval)
{
  std::thread([func, interval]()
  { 
    while (true)
    { 
      auto x = std::chrono::steady_clock::now() + std::chrono::milliseconds(interval);
      func();
      std::this_thread::sleep_until(x);
    }
  }).detach();
}

void do_something()
{
  std::cout << "I am doing something" << std::endl;
}

int main()
{
  timer_start(do_something, 1000);
  while (true)
    ;
}

Upvotes: 35

Andreas Hadjigeorgiou
Andreas Hadjigeorgiou

Reputation: 194

This is quite an old post but I found a really easy solution to this and I would like to share it:

the solution is to

#include "unistd.h"

and use the function which is included in the above library,

usleep(int) 

for example this would call a function every 3000 microseconds

int main() {

    int sleep_time = 3000;
    while(true) { 

          usleep(sleep_time);

          call function;
    }

    return 0;
}

I used it as well for serial and parallel codes and works in both cases!

Upvotes: 0

user9335240
user9335240

Reputation: 1789

Sorry, but I didn't find a design simpler than that.

You could, make a class that owns both a thread, and a weak_ptr to itself, to be a "holder" that the callable can see it safely, because the callable will still exists even if the object is destructed. You don't want a dangling pointer.

template<typename T>
struct IntervalRepeater {
    using CallableCopyable = T;
private:
    weak_ptr<IntervalRepeater<CallableCopyable>> holder;
    std::thread theThread;

    IntervalRepeater(unsigned int interval,
            CallableCopyable callable): callable(callable), interval(interval) {}

    void thread() {
        weak_ptr<IntervalRepeater<CallableCopyable>> holder = this->holder;
        theThread = std::thread([holder](){
            // Try to strongify the pointer, to make it survive this loop iteration,
            //    and ensure that this pointer is valid, if not valid, end the loop.
            while (shared_ptr<IntervalRepeater<CallableCopyable>> ptr = holder.lock()) {
                auto x = chrono::steady_clock::now() + chrono::milliseconds(ptr->interval);
                ptr->callable();
                this_thread::sleep_until(x);
            }
        });
    }

public:
    const CallableCopyable callable;
    const unsigned int interval;

    static shared_ptr<IntervalRepeater<T>> createIntervalRepeater(unsigned int interval,
            CallableCopyable callable) {
        std::shared_ptr<IntervalRepeater<CallableCopyable>> ret =
                shared_ptr<IntervalRepeater<CallableCopyable>>(
                        new IntervalRepeater<CallableCopyable>(interval, callable));
        ret->holder = ret;
        ret->thread();

        return ret;
    }

    ~IntervalRepeater() {
        // Detach the thread before it is released.
        theThread.detach();
    }

};

void beginItWaitThenDestruct() {
    auto repeater = IntervalRepeater<function<void()>>::createIntervalRepeater(
            1000, [](){ cout << "A second\n"; });
    std::this_thread::sleep_for(std::chrono::milliseconds(3700));
}

int main() {
    beginItWaitThenDestruct();
    // Wait for another 2.5 seconds, to test whether there is still an effect of the object
    //   or no.
    std::this_thread::sleep_for(std::chrono::milliseconds(2500));
    return 0;
}

Upvotes: 0

RawBean
RawBean

Reputation: 462

If you're coding with Visual C++, you could add a timer element to the form you want to call a periodic function (here it's called my form is MainForm, and my timer MainTimer). Add a call to the tick event in the "Events". The designer will add such line in your .h file:

this->MainTimer->Enabled = true;
this->MainTimer->Interval = 10;
this->MainTimer->Tick += gcnew System::EventHandler(this, &MainForm::MainTimer_Tick);

Then, at each interval (specified in ms), the application will call this function

private: System::Void MainTimer_Tick(System::Object^  sender, System::EventArgs^  e) {
   /// Enter your periodic code there
}

Upvotes: 1

Ajay
Ajay

Reputation: 18411

It depends on what you would be doing on per interval - displaying time/ticker or something else at specific location of screen/form. Or you may need to send regular data to some connected machine (over socket or pipe). Do you really need 10 millisecond precision?

Depending on requirement, especially the precision requirement, you may have dedicated thread to do 'something', then wait and do same thing again. Or, on Windows, you may use SetTimer that would trigger WM_TIMER event on each interval (it wouldn't require thread). You may also use waitable timer, multimedia timer etc.

At last, but quite important - Do you need platform and compiler compatibility? Meaning that, which OS you would be using, or you need platform independent? What compiler features you are looking for (C++11, C++14 or pre C++11).

Upvotes: 0

user534498
user534498

Reputation: 3984

A simple timer can be implemented as follows,

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

void timer_start(std::function<void(void)> func, unsigned int interval)
{
    std::thread([func, interval]() {
        while (true)
        {
            func();
            std::this_thread::sleep_for(std::chrono::milliseconds(interval));
        }
    }).detach();
}


void do_something()
{
    std::cout << "I am doing something" << std::endl;
}

int main() {
    timer_start(do_something, 1000);

    while(true);
}

This simple solution does not offer a way to stop the timer. The timer will keep running until the program exited.

Upvotes: 23

JMercer
JMercer

Reputation: 372

You could look into threading:

Here's a time interval controlled function implemented in C, using pthread.h, it should be a simple port to C++. Executing a function at specific intervals

Upvotes: 0

Related Questions