javac
javac

Reputation: 461

Counting time with timer in C

I want to run a C program in a specific duration. After this time the program should be terminated. I searched some documents about it but many of them use sleep function. I don't want to use it. I want to check the current time whether it is bigger than the target time in an infinite loop.

For example below code , my target time is 5 and when running time duration is bigger than the 5, the program should be terminated.

But the code causes an infinite loop. How can I solve this problem?

void thread_handler(union sigval sv) {
    char *s = sv.sival_ptr;
    /* Will print "5 seconds elapsed." */
    puts(s);
}

int main(void) {
    char info[] = "5 seconds elapsed.";
    timer_t timerid;
    struct sigevent sev;
    struct itimerspec trigger;
    struct itimerspec triggerAfter;

    memset(&sev, 0, sizeof(struct sigevent));
    memset(&trigger, 0, sizeof(struct itimerspec));

    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_notify_function = &thread_handler;
    sev.sigev_value.sival_ptr = &info;

    timer_create(CLOCK_REALTIME, &sev, &timerid);

    trigger.it_value.tv_sec = 5;

    timer_settime(timerid, 0, &trigger, NULL); 

    timer_gettime(timerid,&trigger);
    while (1) {
        if ((int)trigger.it_value.tv_sec > 5) { //checking the current time is bigger than the target time, it it is then exit from the program
            timer_delete(timerid);
            exit(0);
        }
    }
}

Upvotes: 2

Views: 612

Answers (1)

Petr Skocik
Petr Skocik

Reputation: 60056

If you want to check and compare in a busy loop, you can simply call clock_gettime and completely avoid timers. The whole point of a timer is to avoid such busy loops.

In your case your main thread can simply pause and you can exit from the thread_handler function, which is run on a dedicated thread by the timer handler.

#include <time.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
void thread_handler(union sigval sv) {
    char *s = sv.sival_ptr;
    /* Will print "5 seconds elapsed." */
    puts(s);
    exit(0);
}

int main(void) {
    char info[] = "5 seconds elapsed.";
    timer_t timerid;
    struct sigevent sev;
    struct itimerspec trigger;
    struct itimerspec triggerAfter;

    memset(&sev, 0, sizeof(struct sigevent));
    memset(&trigger, 0, sizeof(struct itimerspec));

    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_notify_function = &thread_handler;
    sev.sigev_value.sival_ptr = &info;

    if(0>timer_create(CLOCK_REALTIME, &sev, &timerid)) return perror("timer_create"),1;

    trigger.it_value.tv_sec = 5;

    if(0>timer_settime(timerid, 0, &trigger, NULL)) return perror("timer_settime"),1;

    pause();

}

If you still want to busy check, you need to have the timer_gettime in the waiting loop. Calling it just once won't make the trigger object auto-update on its own.

Upvotes: 2

Related Questions