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
35 extern "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  */
70 typedef 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  */
81 typedef int64_t time_duration_ns;
82 
83 /*!
84  * Convert nanoseconds duration to double seconds.
85  *
86  * @see timepoint_ns
87  * @ingroup aux_util
88  */
89 static 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  */
101 static inline time_duration_ns
102 time_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  */
113 static 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  */
126 static inline timepoint_ns
127 time_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  */
138 static inline bool
140 {
141  int64_t t = (int64_t)a - (int64_t)b;
142  return (-(int64_t)range < t) && (t < (int64_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  */
151 static inline bool
153 {
155 }
156 
157 /*!
158  * Fuzzy comparisons.
159  *
160  * @see timepoint_ns
161  * @ingroup aux_util
162  */
163 static 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  */
175 static inline bool
177 {
179 }
180 
181 /*!
182  * Fuzzy comparisons.
183  *
184  * @see timepoint_ns
185  * @ingroup aux_util
186  */
187 static 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  */
199 static 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  */
214 struct time_state;
215 
216 /*!
217  * Create a struct time_state.
218  *
219  * @public @memberof time_state
220  * @ingroup aux_util
221  */
222 struct time_state *
223 time_state_create(uint64_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  */
234 void
235 time_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  */
247 time_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  */
271 void
272 time_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  */
283 time_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  */
298 time_state_monotonic_to_ts_ns(struct time_state const *state, uint64_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  */
309 uint64_t
310 time_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  */
321 void
322 time_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  */
333 time_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
uint64_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
static bool time_is_less_then_or_within_half_ms(timepoint_ns a, timepoint_ns b)
Fuzzy comparisons.
Definition: u_time.h:176
timepoint_ns time_state_monotonic_to_ts_ns(struct time_state const *state, uint64_t monotonic_ns)
Convert a monotonic system time (such as from Portable Timekeeping) to an adjusted integer timestamp.
Definition: u_time.cpp:107
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
struct time_state * time_state_create(uint64_t offset)
Create a struct time_state.
Definition: u_time.cpp:42
timepoint_ns time_state_get_now(struct time_state const *state)
Get the current time as an integer timestamp.
Definition: u_time.cpp:66
static bool time_is_greater_then_or_within_range(timepoint_ns a, timepoint_ns b, uint64_t range)
Fuzzy comparisons.
Definition: u_time.h:188
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.
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
static bool time_is_less_then_or_within_range(timepoint_ns a, timepoint_ns b, uint64_t range)
Fuzzy comparisons.
Definition: u_time.h:164
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
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 bool time_is_within_range_of_each_other(timepoint_ns a, timepoint_ns b, uint64_t range)
Checks if two timepoints are with a certain range of each other.
Definition: u_time.h:139
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
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.