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 half a millisecond.
58 *
59 * @see timepoint_ns
60 */
61#define U_TIME_HALF_MS_IN_NS (U_TIME_1MS_IN_NS / 2)
62
63/*!
64 * Integer timestamp type.
65 *
66 * @see time_state
67 * @see time_duration_ns
68 * @ingroup aux_util
69 */
70typedef int64_t timepoint_ns;
71
72/*!
73 * Integer duration type in nanoseconds.
74 *
75 * Logical type of timepoint differences.
76 *
77 * @see time_state
78 * @see timepoint_ns
79 * @ingroup aux_util
80 */
81typedef int64_t time_duration_ns;
82
83/*!
84 * Convert nanoseconds duration to double seconds.
85 *
86 * @see timepoint_ns
87 * @ingroup aux_util
88 */
89static inline double
91{
92 return (double)(ns) / (double)(U_TIME_1S_IN_NS);
93}
94
95/*!
96 * Convert float seconds to nanoseconds.
97 *
98 * @see timepoint_ns
99 * @ingroup aux_util
100 */
101static inline time_duration_ns
102time_s_to_ns(double duration)
103{
104 return (time_duration_ns)(duration * (double)U_TIME_1S_IN_NS);
105}
106
107/*!
108 * Convert nanoseconds to double float milliseconds, useful for printing.
109 *
110 * @see timepoint_ns
111 * @ingroup aux_util
112 */
113static inline double
115{
116 return (double)(ns) / (double)(U_TIME_1MS_IN_NS);
117}
118
119/*!
120 * Convert double float milliseconds to nanoseconds, human comprehensible config
121 * inputs. Recommended to keep the absolute value of the input relitively small.
122 *
123 * @see timepoint_ns
124 * @ingroup aux_util
125 */
126static inline timepoint_ns
127time_ms_f_to_ns(double ms_f)
128{
129 return (timepoint_ns)(ms_f * (double)(U_TIME_1MS_IN_NS));
130}
131
132/*!
133 * Checks if two timepoints are with a certain range of each other.
134 *
135 * @see timepoint_ns
136 * @ingroup aux_util
137 */
138static inline bool
140{
141 int64_t t = a - b;
142 return (-range < t) && (t < range);
143}
144
145/*!
146 * Checks if two timepoints are with half a millisecond of each other.
147 *
148 * @see timepoint_ns
149 * @ingroup aux_util
150 */
151static inline bool
153{
155}
156
157/*!
158 * Fuzzy comparisons.
159 *
160 * @see timepoint_ns
161 * @ingroup aux_util
162 */
163static inline bool
165{
166 return a < b || time_is_within_range_of_each_other(a, b, range);
167}
168
169/*!
170 * Fuzzy comparisons.
171 *
172 * @see timepoint_ns
173 * @ingroup aux_util
174 */
175static inline bool
177{
179}
180
181/*!
182 * Fuzzy comparisons.
183 *
184 * @see timepoint_ns
185 * @ingroup aux_util
186 */
187static inline bool
189{
190 return a > b || time_is_within_range_of_each_other(a, b, range);
191}
192
193/*!
194 * Fuzzy comparisons.
195 *
196 * @see timepoint_ns
197 * @ingroup aux_util
198 */
199static inline bool
201{
203}
204
205/*!
206 * @struct time_state util/u_time.h
207 * @brief Time-keeping state structure.
208 *
209 * Exposed as an opaque pointer.
210 *
211 * @see timepoint_ns
212 * @ingroup aux_util
213 */
214struct time_state;
215
216/*!
217 * Create a struct time_state.
218 *
219 * @public @memberof time_state
220 * @ingroup aux_util
221 */
222struct time_state *
223time_state_create(int64_t offset);
224
225
226/*!
227 * Destroy a struct time_state.
228 *
229 * Should not be called simultaneously with any other time_state function.
230 *
231 * @public @memberof time_state
232 * @ingroup aux_util
233 */
234void
235time_state_destroy(struct time_state **state);
236
237/*!
238 * Get the current time as an integer timestamp.
239 *
240 * Does not update internal state for timekeeping.
241 * Should not be called simultaneously with time_state_get_now_and_update.
242 *
243 * @public @memberof time_state
244 * @ingroup aux_util
245 */
247time_state_get_now(struct time_state const *state);
248
249/*!
250 * Get the current time as an integer timestamp and update internal state.
251 *
252 * This should be called regularly, but only from one thread.
253 * It updates the association between the timing sources.
254 *
255 * Should not be called simultaneously with any other time_state function.
256 *
257 * @public @memberof time_state
258 * @ingroup aux_util
259 */
262
263/*!
264 * Convert an integer timestamp to a struct timespec (system time).
265 *
266 * Should not be called simultaneously with time_state_get_now_and_update.
267 *
268 * @public @memberof time_state
269 * @ingroup aux_util
270 */
271void
272time_state_to_timespec(struct time_state const *state, timepoint_ns timestamp, struct timespec *out);
273
274/*!
275 * Convert a struct timespec (system time) to an integer timestamp.
276 *
277 * Should not be called simultaneously with time_state_get_now_and_update.
278 *
279 * @public @memberof time_state
280 * @ingroup aux_util
281 */
283time_state_from_timespec(struct time_state const *state, const struct timespec *timespecTime);
284
285/*!
286 * Convert a monotonic system time (such as from @ref aux_os_time) to an
287 * adjusted integer timestamp.
288 *
289 * Adjustments may need to be applied to achieve the other guarantees that e.g.
290 * CLOCK_MONOTONIC does not provide: this function performs those adjustments.
291 *
292 * Should not be called simultaneously with time_state_get_now_and_update.
293 *
294 * @public @memberof time_state
295 * @ingroup aux_util
296 */
298time_state_monotonic_to_ts_ns(struct time_state const *state, int64_t monotonic_ns);
299
300/*!
301 * Convert a adjusted integer timestamp to an monotonic system time (such as
302 * from @ref aux_os_time).
303 *
304 * Should not be called simultaneously with time_state_get_now_and_update.
305 *
306 * @public @memberof time_state
307 * @ingroup aux_util
308 */
309int64_t
310time_state_ts_to_monotonic_ns(struct time_state const *state, timepoint_ns timestamp);
311
312#if defined(XRT_OS_WINDOWS) || defined(XRT_DOXYGEN)
313/*!
314 * Converts a timestamp to Win32 "QPC" ticks.
315 *
316 * Should not be called simultaneously with time_state_get_now_and_update.
317 *
318 * @public @memberof time_state
319 * @ingroup aux_util
320 */
321void
322time_state_to_win32perfcounter(struct time_state const *state, timepoint_ns timestamp, LARGE_INTEGER *out_qpc_ticks);
323
324/*!
325 * Converts from Win32 "QPC" ticks to timestamp.
326 *
327 * Should not be called simultaneously with time_state_get_now_and_update.
328 *
329 * @public @memberof time_state
330 * @ingroup aux_util
331 */
333time_state_from_win32perfcounter(struct time_state const *state, const LARGE_INTEGER *qpc_ticks);
334#endif // defined(XRT_OS_WINDOWS) || defined(XRT_DOXYGEN)
335
336
337#ifdef __cplusplus
338}
339#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:188
static bool time_is_less_then_or_within_half_ms(timepoint_ns a, timepoint_ns b)
Fuzzy comparisons.
Definition: u_time.h:176
int64_t timepoint_ns
Integer timestamp type.
Definition: u_time.h:70
static double time_ns_to_ms_f(time_duration_ns ns)
Convert nanoseconds to double float milliseconds, useful for printing.
Definition: u_time.h:114
static bool time_is_less_then_or_within_range(timepoint_ns a, timepoint_ns b, int64_t range)
Fuzzy comparisons.
Definition: u_time.h:164
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:90
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:152
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:139
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:127
static bool time_is_greater_then_or_within_half_ms(timepoint_ns a, timepoint_ns b)
Fuzzy comparisons.
Definition: u_time.h:200
int64_t time_duration_ns
Integer duration type in nanoseconds.
Definition: u_time.h:81
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:102
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:61
#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.