Home > OS >  run function every 5s using the parameters in the code
run function every 5s using the parameters in the code

Time:10-25

I need to run my function MyFunc() every 5 seconds using the parameters in the code (i.e. minimum code changes).
There are two parameters in the code: ts and std::chrono::system_clock::now()
How do I write a condition so that I can run my function?

auto ts = std::chrono::system_clock::now()   std::chrono::seconds(1);

do {
    // 1s timer
    if ( ts <= std::chrono::system_clock::now()) {

        // ... doing some work

        // here I need to start MyFunc() every 5s
        if (/* condition */) {
            MyFunc();
        }

        ts  = std::chrono::seconds(1);
    }

} while (isWork);

CodePudding user response:

The way in my mind is to check whether the time passed is greater than 5 seconds. You could do something similar to this, where there is a separate variable to keep track of 5 seconds after the last time that the function was run:

auto ts = std::chrono::system_clock::now()   std::chrono::seconds(1);
auto fiveseconds = std::chrono::system_clock::now()   std::chrono::seconds(5);

do {
    // 1s timer
    if ( ts <= std::chrono::system_clock::now()) {

        // ... doing some work

        // here I need to start MyFunc() every 5s
        if (fiveseconds <= std::chrono::system_clock::now()) {
            MyFunc();
            fiveseconds = std::chrono::system_clock::now()   std::chrono::seconds(5);
        }

        ts  = std::chrono::seconds(1);
    }

} while (isWork);

Note that this may not run it exactly every five seconds, just about when it runs the once-a-second loop, and then checks if it has been over five seconds.

CodePudding user response:

This is how I would do it. I don't use sleep because that could delay shutdown a lot. Instead I use a condition variable to wait at most 5 seconds to check if a stop condition is triggered, but returns immediately if the stop condition is triggered. This make reaction to your stopping much more responsive.

By using std::async the main thread keeps free for other things if needed.

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

using namespace std::chrono_literals; // so we cant type 5s to mean 5 seconds

int main()
{
    bool keep_running{ true };              // a flag indicating if you want to keep processing
    std::condition_variable signal;         // a signal between two threads that (maybe) keep_running has changed value
    std::mutex mtx;                         // a mutex to use with flag/signal. (mutexes are often needed when more then 1 thread is involved)

    std::cout << "press return to stop\n";

    // launch a lambda function in a thread
    // pass the boolean keep running
    auto future = std::async(std::launch::async, [&]
        {
            while (keep_running)
            {
                std::cout << ".";   // show we are looping

                // get a lock, this is needed for safe waiting on the signal
                std::unique_lock<std::mutex>  lock{ mtx };

                // I tend to never use sleep, but use a condition variable to
                // be able to respond faster
                // wait_for waits for 5s OR until keep_runnning is false
                signal.wait_for(lock, 51s, [&] { return !keep_running; }); 
            }
        });

    auto c = getchar();
    std::cout << "stopping\n";

    // update keep_running and condition variable in a lock too
    {
        std::unique_lock<std::mutex> lock{ mtx };
        keep_running = false;
        signal.notify_one();
    }

    future.get(); // wait for thread to have stopped.
    std::cout << "stopped\n";

    return 0;
}
  • Related