How can I set a triggering time to multiple functions?

I am a beginner in C++. Let's say I have 4 functions (func1(), func2(), func3() & func4()). And let's say I have assigned time values to be triggered for each function as below,

func1() - after each 3 seconds
func2() - after each 6 seconds
func3() - after each 9 seconds
func4() - after each 12 seconds

Eg:
* After 3 seconds from the starting time of the program - func1()
* After 6 seconds from the starting time of the program - func1(), func2()
* After 9 seconds from the starting time of the program - func1(), func3()
* After 12 seconds from the starting time of the program - func1(), func2(), func4()


How can I do this? A massive thank for helping me!
This is to describe the approach I would take. This is not a working example, but I am sure you could make it into one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
unsigned int counter = 0;
while (someCondition)
{
      start funct1 in a thread.
      if (counter%2==0) start funct2 in another thread.
      if (counter%3==0) start funct3 in another thread.
      if (counter%4==0) start funct4 in another thread.
      counter = counter + 1
      sleep for 3 seconds
      join the thread of func1
      join the thread of func2
      join the thread of func3
      join the thread of func4
}


This should approximate the functionality you describe. I opted to execute the functions in separate threads so the time required for the execution of the function is less relevant for the timing of your program, but there are some restrictions.
- The functions must all return within the sleep time (you can do a lot in 3 seconds)
- The functions may not ever throw an exception (consider a try-catch around the function if you are not sure)
- The 3 seconds will be approximated, but probably the interval will be a bit longer
Last edited on
It is really that simple:
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
// this_thread::sleep_for example
#include <iostream>       // std::cout, std::endl
#include <thread>         // std::this_thread::sleep_for
#include <chrono>         // std::chrono::seconds
 
int main() 
{
  for (int i=0; i < 4; ++i)
  {
    std::this_thread::sleep_for(std::chrono::seconds(3));
    switch(i)
    {
      case 0:
        func1();
        break;
...
      case 3:
        func1();
        func2();
        func4();
        break;
    }
  }

  return 0;
}
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)
}
Topic archived. No new replies allowed.