#include #include #include #include #include /* calculate the time-difference between t1 and t2, assuming t2 comes no earlier * then t1. * stores the time difference in 'diff'. * returns 0 on success, -1 if t1 comes after t2. */ int time_diff(struct timeval *t1, struct timeval *t2, struct timeval *diff) { /* sanity check. */ if (t1->tv_sec > t2->tv_sec || (t1->tv_sec == t2->tv_sec && t1->tv_usec > t2->tv_usec)) return -1; if (t2->tv_sec == t1->tv_sec) { diff->tv_sec = 0; diff->tv_usec = t2->tv_usec - t2->tv_usec; } else { diff->tv_sec = t2->tv_sec - t1->tv_sec; if (t2->tv_usec >= t1->tv_usec) diff->tv_usec = t2->tv_usec - t1->tv_usec; else { diff->tv_usec = 1000000 + t2->tv_usec - t1->tv_usec; diff->tv_sec -= 1; } } return 0; } /* perform a time-print every 1 second. handle time drifts appropriately. * if we missed the timer by more then 1 second, skip the missed timers. * (the other option would have been to trigger the timer several times in * a row in such situation, but this is not appropriate for our use-case). */ int main() { struct timeval before; struct timeval now; struct timeval diff; struct timeval delay; if (gettimeofday(&before, NULL)) { fprintf(stderr, "Error getting start time - %s\n", strerror(errno)); return 1; } printf("Repetitive printing of time, 1 second delay.\n"); if (gettimeofday(&before, NULL)) { fprintf(stderr, "Error getting first time - %s\n", strerror(errno)); return 1; } printf("Tick: %lu:%.6lu, next: %lu:%.6lu\n", before.tv_sec, before.tv_usec, before.tv_sec + 1, before.tv_usec); delay.tv_sec = 1; delay.tv_usec = 0; /* we run in an endless loop. */ while (1) { /* try to delay for the remaining time for the next interval. */ if (select(0, NULL, NULL, NULL, &delay)) { if (errno != EINTR) { fprintf(stderr, "Error from select - %s\n", strerror(errno)); return 1; } printf("premature wakeup, got signal.\n"); } /* get the time, calculate diff from 'before'. */ if (gettimeofday(&now, NULL)) { fprintf(stderr, "Error getting 'now' time - %s\n", strerror(errno)); return 1; } if (time_diff(&before, &now, &diff)) { fprintf(stderr, "Error - time just sliped backwards, before - %lu:%lu, now - %lu:%lu\n", before.tv_sec, before.tv_usec, now.tv_sec, now.tv_usec); return 1; } /* more then 1 second passed - print a tick. */ if (diff.tv_sec >= 1) { /* calculate how much we need to sleep until the next tick. * don't forget to handle time drifts. */ if (diff.tv_usec == 0) { delay.tv_sec = 1; delay.tv_usec = 0; } else { delay.tv_sec = 0; delay.tv_usec = 1000000 - diff.tv_usec; } printf("Tick: %lu:%.6lu, till_next: %lu:%.6lu\n", now.tv_sec, now.tv_usec, delay.tv_sec, delay.tv_usec); } /* calculate how much we have left to sleep until the tick. */ delay.tv_sec = 0; delay.tv_usec = 1000000 - diff.tv_usec; } return 0; }