-
Notifications
You must be signed in to change notification settings - Fork 0
/
time.c
146 lines (115 loc) · 3.69 KB
/
time.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "time.h"
#include "math.h"
#include <assert.h>
#include <math.h>
#include <time.h>
static void ticker_tick(struct ticker* ticker, struct duration delta);
static void ticker_reset(struct ticker* ticker);
void tick_timer(struct timer* const timer, const struct duration delta)
{
ticker_tick(&timer->ticker, delta);
}
void reset_timer(struct timer* const timer)
{
ticker_reset(&timer->ticker);
}
bool timer_expires(const struct timer* const timer)
{
return get_elapsed_time_ratio(timer) >= 1;
}
float get_elapsed_time_ratio(const struct timer* const timer)
{
assert(timer->duration.msecs != 0);
return CLAMP(0, 1, (float)((double)timer->ticker.elapsed.msecs / (double)timer->duration.msecs));
}
struct duration get_remaining_time(const struct timer* const timer)
{
return duration_diff(timer->duration, timer->ticker.elapsed);
}
struct duration get_overflow_time(const struct timer* const timer)
{
return duration_diff(timer->ticker.elapsed, timer->duration);
}
void sleep_for(const struct duration duration)
{
if (duration.msecs < 0) {
return;
}
struct timespec time_spec = { 0 };
time_spec.tv_sec = (time_t)duration.msecs / 1000;
time_spec.tv_nsec = (time_t)duration.msecs % 1000 * 1000000;
int slept = -1;
do {
slept = nanosleep(&time_spec, &time_spec);
} while (slept != 0);
}
struct moment moment_from_duration(const struct duration duration, const enum time_precision precision)
{
struct moment moment = { 0 };
struct duration current = duration;
if (precision <= time_hour) {
double hours = (double)current.msecs / time_hour;
if (precision == time_hour) {
hours = ceil(hours);
}
moment.hours = (unsigned int)hours;
current.msecs -= (unsigned long)moment.hours * time_hour;
}
if (precision <= time_min) {
double mins = (double)current.msecs / time_min;
if (precision == time_min) {
mins = ceil(mins);
}
mins = MIN(mins, 59);
moment.mins = (unsigned int)mins;
current.msecs -= (unsigned long)moment.mins * time_min;
}
if (precision <= time_sec) {
double secs = (double)current.msecs / time_sec;
if (precision == time_sec) {
secs = ceil(secs);
}
secs = MIN(secs, 59);
moment.secs = (unsigned int)secs;
current.msecs -= (unsigned long)moment.secs * time_sec;
}
if (precision <= time_msec) {
double msecs = (double)current.msecs / time_msec;
if (precision == time_msec) {
msecs = ceil(msecs);
}
msecs = MIN(msecs, 999);
moment.msecs = (unsigned int)msecs;
current.msecs -= (unsigned long)moment.msecs * time_msec;
}
return moment;
}
struct duration duration_from_moment(const struct moment moment)
{
return (struct duration) {
.msecs = moment.hours * time_hour + moment.mins * time_min + moment.secs * time_sec + moment.msecs * time_msec,
};
}
struct duration duration_diff(const struct duration duration, const struct duration other)
{
return (struct duration) {
.msecs = duration.msecs > other.msecs ? duration.msecs - other.msecs : 0,
};
}
struct duration get_monotonic_time(void)
{
struct timespec time = { 0 };
clock_gettime(CLOCK_MONOTONIC, &time);
unsigned long msecs = 0;
msecs += time.tv_sec * time_sec;
msecs += (long)round((double)time.tv_nsec / 1.0e6);
return (struct duration) { .msecs = msecs };
}
static void ticker_tick(struct ticker* const ticker, const struct duration delta)
{
ticker->elapsed.msecs += delta.msecs;
}
static void ticker_reset(struct ticker* const ticker)
{
ticker->elapsed.msecs = 0;
}