Monado OpenXR Runtime
u_time.h
Go to the documentation of this file.
1// Copyright 2019-2020, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Time-keeping: a clock that is steady, convertible to system time, and
6 * ideally high-resolution.
7 *
8 * Designed to suit the needs of OpenXR: you can and should use something
9 * simpler (like @ref aux_os_time) for most purposes that aren't in OpenXR
10 * interface code.
11 *
12 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
13 * @ingroup aux_util
14 *
15 * @see time_state
16 */
17
18#pragma once
19
20#include "xrt/xrt_compiler.h"
21
22#include <stdint.h>
23#include <time.h> // IWYU pragma: keep
24
25#if defined(XRT_ENV_MINGW)
26// That define is needed before to include windows.h, to avoid a collision
27// between the 'byte' type defined by windows and std::byte defined in cstddef
28// since C++17
29#define byte win_byte_override
30#include <windows.h>
31#undef byte
32#endif
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38//! Helper define to make code more readable.
39#define U_1_000_000_000 (1000 * 1000 * 1000)
40
41/*!
42 * The number of nanoseconds in a second.
43 *
44 * @see timepoint_ns
45 * @ingroup time_ns_to_s
46 */
47#define U_TIME_1S_IN_NS U_1_000_000_000
48
49/*!
50 * The number of nanoseconds in a millisecond.
51 *
52 * @see timepoint_ns
53 */
54#define U_TIME_1MS_IN_NS (1000 * 1000)
55
56/*
57 * The number of nanoseconds in a microsecond.
58
59 * @see timepoint_ns
60 */
61#define U_TIME_1US_IN_NS 1000
62
63/*!
64 * The number of nanoseconds in half a millisecond.
65 *
66 * @see timepoint_ns
67 */
68#define U_TIME_HALF_MS_IN_NS (U_TIME_1MS_IN_NS / 2)
69
70/*!
71 * Integer timestamp type.
72 *
73 * @see time_state
74 * @see time_duration_ns
75 * @ingroup aux_util
76 */
77typedef int64_t timepoint_ns;
78
79/*!
80 * Integer duration type in nanoseconds.
81 *
82 * Logical type of timepoint differences.
83 *
84 * @see time_state
85 * @see timepoint_ns
86 * @ingroup aux_util
87 */
88typedef int64_t time_duration_ns;
89
90/*!
91 * Convert nanoseconds duration to double seconds.
92 *
93 * @see timepoint_ns
94 * @ingroup aux_util
95 */
96static inline double
98{
99 return (double)(ns) / (double)(U_TIME_1S_IN_NS);
100}
101
102/*!
103 * Convert float seconds to nanoseconds.
104 *
105 * @see timepoint_ns
106 * @ingroup aux_util
107 */
108static inline time_duration_ns
109time_s_to_ns(double duration)
110{
111 return (time_duration_ns)(duration * (double)U_TIME_1S_IN_NS);
112}
113
114/*!
115 * Convert nanoseconds to double float milliseconds, useful for printing.
116 *
117 * @see timepoint_ns
118 * @ingroup aux_util
119 */
120static inline double
122{
123 return (double)(ns) / (double)(U_TIME_1MS_IN_NS);
124}
125
126/*!
127 * Convert double float milliseconds to nanoseconds, human comprehensible config
128 * inputs. Recommended to keep the absolute value of the input relitively small.
129 *
130 * @see timepoint_ns
131 * @ingroup aux_util
132 */
133static inline timepoint_ns
134time_ms_f_to_ns(double ms_f)
135{
136 return (timepoint_ns)(ms_f * (double)(U_TIME_1MS_IN_NS));
137}
138
139/*!
140 * Checks if two timepoints are with a certain range of each other.
141 *
142 * @see timepoint_ns
143 * @ingroup aux_util
144 */
145static inline bool
147{
148 int64_t t = a - b;
149 return (-range < t) && (t < range);
150}
151
152/*!
153 * Checks if two timepoints are with half a millisecond of each other.
154 *
155 * @see timepoint_ns
156 * @ingroup aux_util
157 */
158static inline bool
160{
162}
163
164/*!
165 * Fuzzy comparisons.
166 *
167 * @see timepoint_ns
168 * @ingroup aux_util
169 */
170static inline bool
172{
173 return a < b || time_is_within_range_of_each_other(a, b, range);
174}
175
176/*!
177 * Fuzzy comparisons.
178 *
179 * @see timepoint_ns
180 * @ingroup aux_util
181 */
182static inline bool
184{
186}
187
188/*!
189 * Fuzzy comparisons.
190 *
191 * @see timepoint_ns
192 * @ingroup aux_util
193 */
194static inline bool
196{
197 return a > b || time_is_within_range_of_each_other(a, b, range);
198}
199
200/*!
201 * Fuzzy comparisons.
202 *
203 * @see timepoint_ns
204 * @ingroup aux_util
205 */
206static inline bool
208{
210}
211
212/*!
213 * @struct time_state util/u_time.h
214 * @brief Time-keeping state structure.
215 *
216 * Exposed as an opaque pointer.
217 *
218 * @see timepoint_ns
219 * @ingroup aux_util
220 */
221struct time_state;
222
223/*!
224 * Create a struct time_state.
225 *
226 * @public @memberof time_state
227 * @ingroup aux_util
228 */
229struct time_state *
230time_state_create(int64_t offset);
231
232
233/*!
234 * Destroy a struct time_state.
235 *
236 * Should not be called simultaneously with any other time_state function.
237 *
238 * @public @memberof time_state
239 * @ingroup aux_util
240 */
241void
242time_state_destroy(struct time_state **state);
243
244/*!
245 * Get the current time as an integer timestamp.
246 *
247 * Does not update internal state for timekeeping.
248 * Should not be called simultaneously with time_state_get_now_and_update.
249 *
250 * @public @memberof time_state
251 * @ingroup aux_util
252 */
254time_state_get_now(struct time_state const *state);
255
256/*!
257 * Get the current time as an integer timestamp and update internal state.
258 *
259 * This should be called regularly, but only from one thread.
260 * It updates the association between the timing sources.
261 *
262 * Should not be called simultaneously with any other time_state function.
263 *
264 * @public @memberof time_state
265 * @ingroup aux_util
266 */
269
270/*!
271 * Convert an integer timestamp to a struct timespec (system time).
272 *
273 * Should not be called simultaneously with time_state_get_now_and_update.
274 *
275 * @public @memberof time_state
276 * @ingroup aux_util
277 */
278void
279time_state_to_timespec(struct time_state const *state, timepoint_ns timestamp, struct timespec *out);
280
281/*!
282 * Convert a struct timespec (system time) to an integer timestamp.
283 *
284 * Should not be called simultaneously with time_state_get_now_and_update.
285 *
286 * @public @memberof time_state
287 * @ingroup aux_util
288 */
290time_state_from_timespec(struct time_state const *state, const struct timespec *timespecTime);
291
292/*!
293 * Convert a monotonic system time (such as from @ref aux_os_time) to an
294 * adjusted integer timestamp.
295 *
296 * Adjustments may need to be applied to achieve the other guarantees that e.g.
297 * CLOCK_MONOTONIC does not provide: this function performs those adjustments.
298 *
299 * Should not be called simultaneously with time_state_get_now_and_update.
300 *
301 * @public @memberof time_state
302 * @ingroup aux_util
303 */
305time_state_monotonic_to_ts_ns(struct time_state const *state, int64_t monotonic_ns);
306
307/*!
308 * Convert a adjusted integer timestamp to an monotonic system time (such as
309 * from @ref aux_os_time).
310 *
311 * Should not be called simultaneously with time_state_get_now_and_update.
312 *
313 * @public @memberof time_state
314 * @ingroup aux_util
315 */
316int64_t
317time_state_ts_to_monotonic_ns(struct time_state const *state, timepoint_ns timestamp);
318
319#if defined(XRT_OS_WINDOWS) || defined(XRT_DOXYGEN)
320/*!
321 * Converts a timestamp to Win32 "QPC" ticks.
322 *
323 * Should not be called simultaneously with time_state_get_now_and_update.
324 *
325 * @public @memberof time_state
326 * @ingroup aux_util
327 */
328void
329time_state_to_win32perfcounter(struct time_state const *state, timepoint_ns timestamp, LARGE_INTEGER *out_qpc_ticks);
330
331/*!
332 * Converts from Win32 "QPC" ticks to timestamp.
333 *
334 * Should not be called simultaneously with time_state_get_now_and_update.
335 *
336 * @public @memberof time_state
337 * @ingroup aux_util
338 */
340time_state_from_win32perfcounter(struct time_state const *state, const LARGE_INTEGER *qpc_ticks);
341#endif // defined(XRT_OS_WINDOWS) || defined(XRT_DOXYGEN)
342
343
344#ifdef __cplusplus
345}
346#endif
static bool time_is_greater_then_or_within_range(timepoint_ns a, timepoint_ns b, int64_t range)
Fuzzy comparisons.
Definition: u_time.h:195
static bool time_is_less_then_or_within_half_ms(timepoint_ns a, timepoint_ns b)
Fuzzy comparisons.
Definition: u_time.h:183
int64_t timepoint_ns
Integer timestamp type.
Definition: u_time.h:77
static double time_ns_to_ms_f(time_duration_ns ns)
Convert nanoseconds to double float milliseconds, useful for printing.
Definition: u_time.h:121
static bool time_is_less_then_or_within_range(timepoint_ns a, timepoint_ns b, int64_t range)
Fuzzy comparisons.
Definition: u_time.h:171
timepoint_ns time_state_get_now(struct time_state const *state)
Get the current time as an integer timestamp.
Definition: u_time.cpp:66
timepoint_ns time_state_from_timespec(struct time_state const *state, const struct timespec *timespecTime)
Convert a struct timespec (system time) to an integer timestamp.
Definition: u_time.cpp:94
timepoint_ns time_state_from_win32perfcounter(struct time_state const *state, const LARGE_INTEGER *qpc_ticks)
Converts from Win32 "QPC" ticks to timestamp.
struct time_state * time_state_create(int64_t offset)
Create a struct time_state.
Definition: u_time.cpp:42
timepoint_ns time_state_get_now_and_update(struct time_state *state)
Get the current time as an integer timestamp and update internal state.
Definition: u_time.cpp:74
static double time_ns_to_s(time_duration_ns ns)
Convert nanoseconds duration to double seconds.
Definition: u_time.h:97
static bool time_is_within_half_ms(timepoint_ns a, timepoint_ns b)
Checks if two timepoints are with half a millisecond of each other.
Definition: u_time.h:159
int64_t time_state_ts_to_monotonic_ns(struct time_state const *state, timepoint_ns timestamp)
Convert a adjusted integer timestamp to an monotonic system time (such as from Portable Timekeeping).
Definition: u_time.cpp:115
void time_state_to_timespec(struct time_state const *state, timepoint_ns timestamp, struct timespec *out)
Convert an integer timestamp to a struct timespec (system time).
Definition: u_time.cpp:82
static bool time_is_within_range_of_each_other(timepoint_ns a, timepoint_ns b, int64_t range)
Checks if two timepoints are with a certain range of each other.
Definition: u_time.h:146
void time_state_to_win32perfcounter(struct time_state const *state, timepoint_ns timestamp, LARGE_INTEGER *out_qpc_ticks)
Converts a timestamp to Win32 "QPC" ticks.
static timepoint_ns time_ms_f_to_ns(double ms_f)
Convert double float milliseconds to nanoseconds, human comprehensible config inputs.
Definition: u_time.h:134
static bool time_is_greater_then_or_within_half_ms(timepoint_ns a, timepoint_ns b)
Fuzzy comparisons.
Definition: u_time.h:207
int64_t time_duration_ns
Integer duration type in nanoseconds.
Definition: u_time.h:88
timepoint_ns time_state_monotonic_to_ts_ns(struct time_state const *state, int64_t monotonic_ns)
Convert a monotonic system time (such as from Portable Timekeeping) to an adjusted integer timestamp.
Definition: u_time.cpp:107
static time_duration_ns time_s_to_ns(double duration)
Convert float seconds to nanoseconds.
Definition: u_time.h:109
void time_state_destroy(struct time_state **state)
Destroy a struct time_state.
Definition: u_time.cpp:53
Time-keeping state structure.
Definition: u_time.cpp:30
#define U_TIME_HALF_MS_IN_NS
The number of nanoseconds in half a millisecond.
Definition: u_time.h:68
#define U_TIME_1S_IN_NS
The number of nanoseconds in a second.
Definition: u_time.h:47
#define U_TIME_1MS_IN_NS
The number of nanoseconds in a millisecond.
Definition: u_time.h:54
Header holding common defines.