forked from sysprog21/matrix_oo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
stopwatch.c
109 lines (96 loc) · 2.13 KB
/
stopwatch.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include "stopwatch.h"
struct StopwatchInternal {
bool running;
struct timespec last_time;
struct timespec total;
};
static struct timespec clock_time()
{
struct timespec time_now;
clock_gettime(CLOCK_REALTIME, &time_now);
return time_now;
}
static struct timespec time_diff(struct timespec t1, struct timespec t2)
{
struct timespec diff;
if (t2.tv_nsec - t1.tv_nsec < 0) {
diff.tv_sec = t2.tv_sec - t1.tv_sec - 1;
diff.tv_nsec = t2.tv_nsec - t1.tv_nsec + 1000000000;
} else {
diff.tv_sec = t2.tv_sec - t1.tv_sec;
diff.tv_nsec = t2.tv_nsec - t1.tv_nsec;
}
return diff;
}
static struct timespec time_add(struct timespec t1, struct timespec t2)
{
long sec = t2.tv_sec + t1.tv_sec;
long nsec = t2.tv_nsec + t1.tv_nsec;
if (nsec >= 1000000000) {
nsec -= 1000000000;
sec++;
}
return (struct timespec) {
.tv_sec = sec, .tv_nsec = nsec
};
}
void reset(watch_p Q)
{
Q->running = false;
Q->last_time = (struct timespec) {
0, 0
};
Q->total = (struct timespec) {
0, 0
};
}
watch_p create(void)
{
watch_p S = malloc(sizeof(struct StopwatchInternal));
if (!S)
return NULL;
reset(S);
return S;
}
void destroy(watch_p S)
{
free(S);
}
void start(watch_p Q)
{
if (!(Q->running)) {
Q->running = true;
Q->total = (struct timespec) {
0, 0
};
Q->last_time = clock_time();
}
}
void stop(watch_p Q)
{
if (Q->running) {
Q->total = time_add(Q->total, time_diff((Q->last_time), clock_time()));
Q->running = false;
}
}
double read(watch_p Q)
{
if (Q->running) {
struct timespec t = clock_time();
Q->total = time_add(Q->total, time_diff(Q->last_time, t));
Q->last_time = t;
}
return (Q->total.tv_sec * 1000000.0 + Q->total.tv_nsec / 1000.0) / 1000000.0;
}
/* API gateway */
struct __STOPWATCH_API__ Stopwatch = {
.create = create,
.destroy = destroy,
.start = start,
.stop = stop,
.reset = reset,
.read = read,
};