Execute a method every x seconds in C

后端 未结 4 999
别那么骄傲
别那么骄傲 2021-01-06 00:29

Is there an example of a working timer that executes some function every x amount seconds using C.

I\'d appreciate an example working code.

相关标签:
4条回答
  • 2021-01-06 00:34

    IMO, in this case, you can utilize gettimeofday() into algorithm like: use such a while(1) that counts time difference between current time and last_execution_time, everytime the difference reach 1 seconds, update the last_execution_time and call the function that supposed to run in every 1 second.

    #include <stdio.h>
    #include <sys/time.h>
    
    #DEFINE DESIRED_INTERVAL 1  //1 second
    int get_tv_cur_minus_given(struct timeval *tv, struct timeval *tp_given, int *sign)
    {
        struct timeval tp_cur;
    
    
        gettimeofday(&tp_cur,NULL);
    
        tv->tv_sec  = tp_cur.tv_sec - tp_given->tv_sec;
        tv->tv_usec = tp_cur.tv_usec - tp_given->tv_usec;
    
        if(tv->tv_sec > 0) {
            *sign = 1;
            if(tv->tv_usec < 0) {
                tv->tv_sec--;
                tv->tv_usec = 1000000 + tv->tv_usec;
            }
        }else
        if(tv->tv_sec == 0) {
            if(tv->tv_usec == 0)
                *sign = 0;
            else
            if(tv->tv_usec < 0) {
                *sign = -1;
                tv->tv_usec *= -1;
            }else
                *sign = 1;
        }else {
            *sign = -1;
            if(tv->tv_usec > 0) {
                tv->tv_sec++;
                tv->tv_usec = 1000000 - tv->tv_usec;
            }else
            if(tv->tv_usec < 0)
                tv->tv_usec *= -1;
        return 0;
            }
    }
    
    int main()
    {
        struct timeval      tv_last_run;
        struct timeval  tv_diff;
        int sign;
    
    
        while(true)
        {
    
         get_tv_cur_minus_given(&tv_diff, &tv_last_run, &sign);
    
            if(tv_diff.tv_sec > DESIRED_INTERVAL)
            {
                gettimeofday(&tv_last_run,NULL);
                printf("\ncall the func here");
            }
        }
    
        return 0;
    }
    

    In case you need different thread out of main thread, move the lines inside main() into a function pointer and pass it through pthread_create function, eg :

    void *threadproc(void *arg)
    {
       while(1)
       {
           //put the same lines as inside main() function in above code snippet. .
       }
    }
    pthread_create(&tid, NULL, &threadproc, NULL);
    
    0 讨论(0)
  • 2021-01-06 00:35

    There are various legacy ways to do this using interval timers and signals, but I'm going to present two modern approaches:

    Using POSIX timers

    The POSIX timer_create function creates a timer that can be configured to deliver a one-off or periodic notification when the timer expires. When creating the timer, you can request either delivery via a signal or in a new thread. Since using signals correctly is complicated (there are strict rules about what you can and cannot do from a signal handler, and breaking the rules often "seems to work" until you get unlucky), I would recommend using thread-based delivery.

    Rolling your own timer with a thread

    This is really as easy as it sounds. Make a new thread that goes into a loop sleeping and doing whatever you need done every time the desired time has elapsed.

    0 讨论(0)
  • 2021-01-06 00:55

    If we do not want threads, we could use sleep

    int time = 10;
    printf("time: %ds\n", time);
    int i = 0;
    while(i<time) {
    
            printf("doing stuff in duration %d\n", i);
            //stuff();
            sleep(1);
            i++;
    }
    

    The stuff is started every 1s, so we hope it can be done in this duration, otherwise it must take care of resources.

    0 讨论(0)
  • 2021-01-06 00:57

    You could spawn a new thread:

    void *threadproc(void *arg)
    {
        while(!done)
        {
            sleep(delay_in_seconds);
            call_function();
        }
        return 0;
    }
    ...
    pthread_t tid;
    pthread_create(&tid, NULL, &threadproc, NULL);
    

    Or, you could set an alarm with alarm(2) or setitimer(2):

    void on_alarm(int signum)
    {
        call_function();
        if(!done)
            alarm(delay_in_seconds);  // Reschedule alarm
    }
    ...
    // Setup on_alarm as a signal handler for the SIGALRM signal
    struct sigaction act;
    act.sa_handler = &on_alarm;
    act.sa_mask = 0;
    act.sa_flags = SA_RESTART;  // Restart interrupted system calls
    sigaction(SIGALRM, &act, NULL);
    
    alarm(delay_in_seconds);  // Setup initial alarm
    

    Of course, both of these methods have the problem that the function you're calling periodically needs to be thread-safe.

    The signal method is particularly dangerous because it must also be async-safe, which is very hard to do -- even something as simple as printf is unsafe because printf might allocate memory, and if the SIGALRM interrupted a call to malloc, you're in trouble because malloc is not reentrant. So I wouldn't recommend the signal method, unless all you do is set a flag in the signal handler which later gets checked by some other function, which puts you back in the same place as the threaded version.

    0 讨论(0)
提交回复
热议问题