1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
#include <iostream>
#include <atomic>
#include <chrono>
#include <thread>
#include <ctime>
#include <string>
// flag to signal end of program
// made global for brevity in this toy example
static std::atomic<bool> program_end{false} ;
// periodically call the callable object (function) fn once every period_secs seconds,
// forwarding the arguments in the pack args
// note: to pass an arg by reference, wrap it with std::ref or std::cref
// see: https://en.cppreference.com/w/cpp/utility/functional/ref
template < typename FN, typename... ARGS >
void periodic_call( unsigned int period_secs, FN&& fn, ARGS&&... args )
{
const auto period = std::chrono::seconds(period_secs) ;
// thread function: call fn once every period_secs seconds till program_end is set
const auto thread_fn = [ period, &fn, &args... ] ()
{
while( !program_end )
{
std::forward<FN>(fn)( std::forward<ARGS>(args)... ) ;
std::this_thread::sleep_for(period) ;
}
};
// start a detached thread to run in the background
std::thread(thread_fn).detach() ;
}
std::string now() // TO DO: make this thread-safe
{
const auto t = std::time(nullptr) ;
const std::string str = std::ctime( std::addressof(t) ) ;
return str.substr(11,8) ; // return "HH:MM:SS"
}
void func1() { std::cout << now() << " func1\n" ; }
void func2( int v, double d )
{
std::cout << now() << " func2(" << v << "," << d << ")\n" ;
}
int main()
{
std::cout << "press enter to end program\n\n" ;
periodic_call( 3, func1 ) ; // call func1 once every three seconds
periodic_call( 6, func2, 999, 1.2 ) ; // call func2(999,1.2) once every six seconds
periodic_call( 9, [] { std::cout << now() << " func3\n" ; } ) ;
periodic_call( 12, [] { std::cout << now() << " func4\n" ; } ) ;
std::cin.get() ;
program_end = true ; // signal end of program
// TO DO: may want to wait for threads to finish
// TO DO: guard access to stdout (one thread at a time)
// (two or more functions may execute concurrently)
}
|