/src/mozilla-central/gfx/vr/osvr/Util/TimeValueC.h
Line | Count | Source (jump to first uncovered line) |
1 | | /** @file |
2 | | @brief Header defining a dependency-free, cross-platform substitute for |
3 | | struct timeval |
4 | | |
5 | | Must be c-safe! |
6 | | |
7 | | @date 2014 |
8 | | |
9 | | @author |
10 | | Sensics, Inc. |
11 | | <http://sensics.com/osvr> |
12 | | */ |
13 | | |
14 | | /* |
15 | | // Copyright 2014 Sensics, Inc. |
16 | | // |
17 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
18 | | // you may not use this file except in compliance with the License. |
19 | | // You may obtain a copy of the License at |
20 | | // |
21 | | // http://www.apache.org/licenses/LICENSE-2.0 |
22 | | // |
23 | | // Unless required by applicable law or agreed to in writing, software |
24 | | // distributed under the License is distributed on an "AS IS" BASIS, |
25 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
26 | | // See the License for the specific language governing permissions and |
27 | | // limitations under the License. |
28 | | */ |
29 | | |
30 | | #ifndef INCLUDED_TimeValueC_h_GUID_A02C6917_124D_4CB3_E63E_07F2DA7144E9 |
31 | | #define INCLUDED_TimeValueC_h_GUID_A02C6917_124D_4CB3_E63E_07F2DA7144E9 |
32 | | |
33 | | /* Internal Includes */ |
34 | | #include <osvr/Util/Export.h> |
35 | | #include <osvr/Util/APIBaseC.h> |
36 | | #include <osvr/Util/AnnotationMacrosC.h> |
37 | | #include <osvr/Util/PlatformConfig.h> |
38 | | #include <osvr/Util/StdInt.h> |
39 | | #include <osvr/Util/BoolC.h> |
40 | | |
41 | | /* Library/third-party includes */ |
42 | | /* none */ |
43 | | |
44 | | /* Standard includes */ |
45 | | /* none */ |
46 | | |
47 | | OSVR_EXTERN_C_BEGIN |
48 | | |
49 | | /** @defgroup UtilTime Timestamp interaction |
50 | | @ingroup Util |
51 | | |
52 | | This provides a level of interoperability with struct timeval on systems |
53 | | with that facility. It provides a neutral representation with sufficiently |
54 | | large types. |
55 | | |
56 | | For C++ code, use of std::chrono or boost::chrono instead is recommended. |
57 | | |
58 | | Note that these time values may not necessarily correlate between processes |
59 | | so should not be used to estimate or measure latency, etc. |
60 | | |
61 | | @{ |
62 | | */ |
63 | | |
64 | | /** @brief The signed integer type storing the seconds in a struct |
65 | | OSVR_TimeValue */ |
66 | | typedef int64_t OSVR_TimeValue_Seconds; |
67 | | /** @brief The signed integer type storing the microseconds in a struct |
68 | | OSVR_TimeValue */ |
69 | | typedef int32_t OSVR_TimeValue_Microseconds; |
70 | | |
71 | | /** @brief Standardized, portable parallel to struct timeval for representing |
72 | | both absolute times and time intervals. |
73 | | |
74 | | Where interpreted as an absolute time, its meaning is to be considered the |
75 | | same as that of the POSIX struct timeval: |
76 | | time since 00:00 Coordinated Universal Time (UTC), January 1, 1970. |
77 | | |
78 | | For best results, please keep normalized. Output of all functions here |
79 | | is normalized. |
80 | | */ |
81 | | typedef struct OSVR_TimeValue { |
82 | | /** @brief Seconds portion of the time value. */ |
83 | | OSVR_TimeValue_Seconds seconds; |
84 | | /** @brief Microseconds portion of the time value. */ |
85 | | OSVR_TimeValue_Microseconds microseconds; |
86 | | } OSVR_TimeValue; |
87 | | |
88 | | #ifdef OSVR_HAVE_STRUCT_TIMEVAL |
89 | | /** @brief Gets the current time in the TimeValue. Parallel to gettimeofday. */ |
90 | | OSVR_UTIL_EXPORT void osvrTimeValueGetNow(OSVR_OUT OSVR_TimeValue *dest) |
91 | | OSVR_FUNC_NONNULL((1)); |
92 | | |
93 | | struct timeval; /* forward declaration */ |
94 | | |
95 | | /** @brief Converts from a TimeValue struct to your system's struct timeval. |
96 | | |
97 | | @param dest Pointer to an empty struct timeval for your platform. |
98 | | @param src A pointer to an OSVR_TimeValue you'd like to convert from. |
99 | | |
100 | | If either parameter is NULL, the function will return without doing |
101 | | anything. |
102 | | */ |
103 | | OSVR_UTIL_EXPORT void |
104 | | osvrTimeValueToStructTimeval(OSVR_OUT struct timeval *dest, |
105 | | OSVR_IN_PTR const OSVR_TimeValue *src) |
106 | | OSVR_FUNC_NONNULL((1, 2)); |
107 | | |
108 | | /** @brief Converts from a TimeValue struct to your system's struct timeval. |
109 | | @param dest An OSVR_TimeValue destination pointer. |
110 | | @param src Pointer to a struct timeval you'd like to convert from. |
111 | | |
112 | | The result is normalized. |
113 | | |
114 | | If either parameter is NULL, the function will return without doing |
115 | | anything. |
116 | | */ |
117 | | OSVR_UTIL_EXPORT void |
118 | | osvrStructTimevalToTimeValue(OSVR_OUT OSVR_TimeValue *dest, |
119 | | OSVR_IN_PTR const struct timeval *src) |
120 | | OSVR_FUNC_NONNULL((1, 2)); |
121 | | #endif |
122 | | |
123 | | /** @brief "Normalizes" a time value so that the absolute number of microseconds |
124 | | is less than 1,000,000, and that the sign of both components is the same. |
125 | | |
126 | | @param tv Address of a struct TimeValue to normalize in place. |
127 | | |
128 | | If the given pointer is NULL, this function returns without doing anything. |
129 | | */ |
130 | | OSVR_UTIL_EXPORT void osvrTimeValueNormalize(OSVR_INOUT_PTR OSVR_TimeValue *tv) |
131 | | OSVR_FUNC_NONNULL((1)); |
132 | | |
133 | | /** @brief Sums two time values, replacing the first with the result. |
134 | | |
135 | | @param tvA Destination and first source. |
136 | | @param tvB second source |
137 | | |
138 | | If a given pointer is NULL, this function returns without doing anything. |
139 | | |
140 | | Both parameters are expected to be in normalized form. |
141 | | */ |
142 | | OSVR_UTIL_EXPORT void osvrTimeValueSum(OSVR_INOUT_PTR OSVR_TimeValue *tvA, |
143 | | OSVR_IN_PTR const OSVR_TimeValue *tvB) |
144 | | OSVR_FUNC_NONNULL((1, 2)); |
145 | | |
146 | | /** @brief Computes the difference between two time values, replacing the first |
147 | | with the result. |
148 | | |
149 | | Effectively, `*tvA = *tvA - *tvB` |
150 | | |
151 | | @param tvA Destination and first source. |
152 | | @param tvB second source |
153 | | |
154 | | If a given pointer is NULL, this function returns without doing anything. |
155 | | |
156 | | Both parameters are expected to be in normalized form. |
157 | | */ |
158 | | OSVR_UTIL_EXPORT void |
159 | | osvrTimeValueDifference(OSVR_INOUT_PTR OSVR_TimeValue *tvA, |
160 | | OSVR_IN_PTR const OSVR_TimeValue *tvB) |
161 | | OSVR_FUNC_NONNULL((1, 2)); |
162 | | |
163 | | /** @brief Compares two time values (assumed to be normalized), returning |
164 | | the same values as strcmp |
165 | | |
166 | | @return <0 if A is earlier than B, 0 if they are the same, and >0 if A |
167 | | is later than B. |
168 | | */ |
169 | | OSVR_UTIL_EXPORT int osvrTimeValueCmp(OSVR_IN_PTR const OSVR_TimeValue *tvA, |
170 | | OSVR_IN_PTR const OSVR_TimeValue *tvB) |
171 | | OSVR_FUNC_NONNULL((1, 2)); |
172 | | |
173 | | OSVR_EXTERN_C_END |
174 | | |
175 | | /** @brief Compute the difference between the two time values, returning the |
176 | | duration as a double-precision floating-point number of seconds. |
177 | | |
178 | | Effectively, `ret = *tvA - *tvB` |
179 | | |
180 | | @param tvA first source. |
181 | | @param tvB second source |
182 | | @return Duration of timespan in seconds (floating-point) |
183 | | */ |
184 | | OSVR_INLINE double |
185 | | osvrTimeValueDurationSeconds(OSVR_IN_PTR const OSVR_TimeValue *tvA, |
186 | 0 | OSVR_IN_PTR const OSVR_TimeValue *tvB) { |
187 | 0 | OSVR_TimeValue A = *tvA; |
188 | 0 | osvrTimeValueDifference(&A, tvB); |
189 | 0 | double dt = A.seconds + A.microseconds / 1000000.0; |
190 | 0 | return dt; |
191 | 0 | } |
192 | | |
193 | | /** @brief True if A is later than B */ |
194 | | OSVR_INLINE OSVR_CBool |
195 | | osvrTimeValueGreater(OSVR_IN_PTR const OSVR_TimeValue *tvA, |
196 | 0 | OSVR_IN_PTR const OSVR_TimeValue *tvB) { |
197 | 0 | if (!tvA || !tvB) { |
198 | 0 | return OSVR_FALSE; |
199 | 0 | } |
200 | 0 | return ((tvA->seconds > tvB->seconds) || |
201 | 0 | (tvA->seconds == tvB->seconds && |
202 | 0 | tvA->microseconds > tvB->microseconds)) |
203 | 0 | ? OSVR_TRUE |
204 | 0 | : OSVR_FALSE; |
205 | 0 | } |
206 | | |
207 | | #ifdef __cplusplus |
208 | | |
209 | | #include <cmath> |
210 | | #include <cassert> |
211 | | |
212 | | /// Returns true if the time value is normalized. Typically used in assertions. |
213 | 0 | inline bool osvrTimeValueIsNormalized(const OSVR_TimeValue &tv) { |
214 | 0 | #ifdef __APPLE__ |
215 | 0 | // apparently standard library used on mac only has floating-point abs? |
216 | 0 | return std::abs(double(tv.microseconds)) < 1000000 && |
217 | 0 | #else |
218 | 0 | return std::abs(tv.microseconds) < 1000000 && |
219 | 0 | #endif |
220 | 0 | ((tv.seconds > 0) == (tv.microseconds > 0)); |
221 | 0 | } |
222 | | |
223 | | /// True if A is later than B |
224 | | inline bool osvrTimeValueGreater(const OSVR_TimeValue &tvA, |
225 | 0 | const OSVR_TimeValue &tvB) { |
226 | 0 | assert(osvrTimeValueIsNormalized(tvA) && |
227 | 0 | "First timevalue argument to comparison was not normalized!"); |
228 | 0 | assert(osvrTimeValueIsNormalized(tvB) && |
229 | 0 | "Second timevalue argument to comparison was not normalized!"); |
230 | 0 | return (tvA.seconds > tvB.seconds) || |
231 | 0 | (tvA.seconds == tvB.seconds && tvA.microseconds > tvB.microseconds); |
232 | 0 | } |
233 | | |
234 | | /// Operator > overload for time values |
235 | 0 | inline bool operator>(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { |
236 | 0 | return osvrTimeValueGreater(tvA, tvB); |
237 | 0 | } |
238 | | |
239 | | /// Operator < overload for time values |
240 | 0 | inline bool operator<(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { |
241 | 0 | // Change the order of arguments before forwarding. |
242 | 0 | return osvrTimeValueGreater(tvB, tvA); |
243 | 0 | } |
244 | | |
245 | | /// Operator == overload for time values |
246 | 0 | inline bool operator==(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { |
247 | 0 | assert( |
248 | 0 | osvrTimeValueIsNormalized(tvA) && |
249 | 0 | "First timevalue argument to equality comparison was not normalized!"); |
250 | 0 | assert( |
251 | 0 | osvrTimeValueIsNormalized(tvB) && |
252 | 0 | "Second timevalue argument to equality comparison was not normalized!"); |
253 | 0 | return (tvA.seconds == tvB.seconds) && |
254 | 0 | (tvA.microseconds == tvB.microseconds); |
255 | 0 | } |
256 | | /// Operator == overload for time values |
257 | 0 | inline bool operator!=(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { |
258 | 0 | assert(osvrTimeValueIsNormalized(tvA) && "First timevalue argument to " |
259 | 0 | "inequality comparison was not " |
260 | 0 | "normalized!"); |
261 | 0 | assert(osvrTimeValueIsNormalized(tvB) && "Second timevalue argument to " |
262 | 0 | "inequality comparison was not " |
263 | 0 | "normalized!"); |
264 | 0 | return (tvA.seconds != tvB.seconds) || |
265 | 0 | (tvA.microseconds != tvB.microseconds); |
266 | 0 | } |
267 | | #endif |
268 | | |
269 | | /** @} */ |
270 | | |
271 | | #endif |