I need to run my function MyFunc()
every five 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()
What do I write in condition
so that I can run my function at the interval?
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. Also this will not be a busy wait loop (low CPU usage) to check if time has passed.
Live demo here (with 1s loop time) https://onlinegdb.com/qYA_IBqFQ
Some background material:
https://www.learncpp.com/cpp-tutorial/introduction-to-lambdas-anonymous-functions/ https://thispointer.com/c11-multithreading-part-9-stdasync-tutorial-example/ https://en.cppreference.com/w/cpp/thread/mutex https://en.cppreference.com/w/cpp/thread/condition_variable (despite its name it is more of an interthread signal then a variable)
#include <future>
#include <chrono>
#include <thread>
#include <iostream>
using namespace std::chrono_literals;
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";
char output_char = 'x';
// launch a lambda function in a thread
// pass the boolean keep running
// [&] captures : output_char, mtx, signal and keep_running by reference
// making them available in the background thread.
// (Make sure these variables 'live' longer then the duration of the thread
// thats why the future.get() later is important).
auto future = std::async(std::launch::async, [&]
{
while (keep_running)
{
std::cout << output_char; // 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, 5s, [&] { 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;
}