Execute a method every x seconds in C

橙三吉。 提交于 2019-12-19 07:53:39

问题


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.


回答1:


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.




回答2:


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.




回答3:


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);


来源:https://stackoverflow.com/questions/13923885/execute-a-method-every-x-seconds-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!