I'm writing a simple program, which checks if elapsed time is more than 1 seconds. I take start time with a clock_gettime(), then I call sleep(5), take new time and I check if the difference is bigger than 1; I sleep 5 seconds, then it should be greater than 5, but my program prints a strange result.
this is the code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main()
{
struct timespec tv1,tv3,expected;
struct timespec nano1;
tv1.tv_nsec = 0;
tv3.tv_nsec = 0;
expected.tv_nsec = 400000;
if(clock_gettime(CLOCK_MONOTONIC,&tv3) == -1){
perror(NULL);
}
sleep(5);
if(clock_gettime(CLOCK_MONOTONIC,&tv1) == -1){
perror(NULL);
}
long nsec = tv1.tv_nsec - tv3.tv_nsec;
if(nsec>expected.tv_nsec){
printf("nsec runned: %ld nsec timeout: %ld\n",nsec,expected.tv_nsec);
}
printf("elapsed nanoseconds: %ld\n",nsec);
if((nsec>expected.tv_nsec))
printf("expired timer\n");
else
printf("not expired timer\n");
exit(EXIT_SUCCESS);
}
Output of my program is:
"elapsed nanoseconds: 145130" and "not expired timeout"
Where is the problem?
The time represented in a
struct timespec
has two components:tv_sec
— atime_t
value for the integer number of seconds.tv_nsec
— a 32-bit integer for the number of nanoseconds, 0..999,999,999Your calculation didn't take into account the difference between the
tv_sec
values. It is somewhat surprising that the difference between the nanosecond values was as large as you say, but far from impossible. To get the whole difference, you need to take into account both thetv_sec
and thetv_nsec
components.sub_timespec()
You can subtract two values (to get the difference) using a function like:
fmt_timespec
You can format it as a floating-point value with the specified number of decimal places using a function like this:
Revised version of code in question
The header
time_io.h
declares the format and scanning functions forstruct timespec
; thetime_math.h
header declares the functions for adding and subtractingstruct timespec
values. It is probably over-compartmenting the code to have that many headers.Example run:
On a Mac running macOS Sierra 10.12.6 (which finally has
clock_gettime()
— earlier versions of Mac OS X did not support it), the resolution ofclock_gettime()
is 1000 nanoseconds, effectively microseconds. So, the last 3 decimal places are always zeros on a Mac.add_timespec()
For completeness, you can add two
struct timespec
values with:scn_timespec()
And the 'scanning' process is messier (input often is messier than output):
You are using the nsec (nanoseconds) portion of the timestamps and totally ignoring the sec (seconds) part. Those timestamps are composed of two integers, and to get any meaning from them you need both.
Ref: http://en.cppreference.com/w/c/chrono/timespec