diff options
Diffstat (limited to 'gfx/vr/osvr/Util/TimeValueC.h')
-rw-r--r-- | gfx/vr/osvr/Util/TimeValueC.h | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/gfx/vr/osvr/Util/TimeValueC.h b/gfx/vr/osvr/Util/TimeValueC.h new file mode 100644 index 000000000..7dcead654 --- /dev/null +++ b/gfx/vr/osvr/Util/TimeValueC.h @@ -0,0 +1,271 @@ +/** @file + @brief Header defining a dependency-free, cross-platform substitute for + struct timeval + + Must be c-safe! + + @date 2014 + + @author + Sensics, Inc. + <http://sensics.com/osvr> +*/ + +/* +// Copyright 2014 Sensics, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#ifndef INCLUDED_TimeValueC_h_GUID_A02C6917_124D_4CB3_E63E_07F2DA7144E9 +#define INCLUDED_TimeValueC_h_GUID_A02C6917_124D_4CB3_E63E_07F2DA7144E9 + +/* Internal Includes */ +#include <osvr/Util/Export.h> +#include <osvr/Util/APIBaseC.h> +#include <osvr/Util/AnnotationMacrosC.h> +#include <osvr/Util/PlatformConfig.h> +#include <osvr/Util/StdInt.h> +#include <osvr/Util/BoolC.h> + +/* Library/third-party includes */ +/* none */ + +/* Standard includes */ +/* none */ + +OSVR_EXTERN_C_BEGIN + +/** @defgroup UtilTime Timestamp interaction + @ingroup Util + + This provides a level of interoperability with struct timeval on systems + with that facility. It provides a neutral representation with sufficiently + large types. + + For C++ code, use of std::chrono or boost::chrono instead is recommended. + + Note that these time values may not necessarily correlate between processes + so should not be used to estimate or measure latency, etc. + + @{ +*/ + +/** @brief The signed integer type storing the seconds in a struct + OSVR_TimeValue */ +typedef int64_t OSVR_TimeValue_Seconds; +/** @brief The signed integer type storing the microseconds in a struct + OSVR_TimeValue */ +typedef int32_t OSVR_TimeValue_Microseconds; + +/** @brief Standardized, portable parallel to struct timeval for representing + both absolute times and time intervals. + + Where interpreted as an absolute time, its meaning is to be considered the + same as that of the POSIX struct timeval: + time since 00:00 Coordinated Universal Time (UTC), January 1, 1970. + + For best results, please keep normalized. Output of all functions here + is normalized. + */ +typedef struct OSVR_TimeValue { + /** @brief Seconds portion of the time value. */ + OSVR_TimeValue_Seconds seconds; + /** @brief Microseconds portion of the time value. */ + OSVR_TimeValue_Microseconds microseconds; +} OSVR_TimeValue; + +#ifdef OSVR_HAVE_STRUCT_TIMEVAL +/** @brief Gets the current time in the TimeValue. Parallel to gettimeofday. */ +OSVR_UTIL_EXPORT void osvrTimeValueGetNow(OSVR_OUT OSVR_TimeValue *dest) + OSVR_FUNC_NONNULL((1)); + +struct timeval; /* forward declaration */ + +/** @brief Converts from a TimeValue struct to your system's struct timeval. + + @param dest Pointer to an empty struct timeval for your platform. + @param src A pointer to an OSVR_TimeValue you'd like to convert from. + + If either parameter is NULL, the function will return without doing + anything. +*/ +OSVR_UTIL_EXPORT void +osvrTimeValueToStructTimeval(OSVR_OUT struct timeval *dest, + OSVR_IN_PTR const OSVR_TimeValue *src) + OSVR_FUNC_NONNULL((1, 2)); + +/** @brief Converts from a TimeValue struct to your system's struct timeval. + @param dest An OSVR_TimeValue destination pointer. + @param src Pointer to a struct timeval you'd like to convert from. + + The result is normalized. + + If either parameter is NULL, the function will return without doing + anything. +*/ +OSVR_UTIL_EXPORT void +osvrStructTimevalToTimeValue(OSVR_OUT OSVR_TimeValue *dest, + OSVR_IN_PTR const struct timeval *src) + OSVR_FUNC_NONNULL((1, 2)); +#endif + +/** @brief "Normalizes" a time value so that the absolute number of microseconds + is less than 1,000,000, and that the sign of both components is the same. + + @param tv Address of a struct TimeValue to normalize in place. + + If the given pointer is NULL, this function returns without doing anything. +*/ +OSVR_UTIL_EXPORT void osvrTimeValueNormalize(OSVR_INOUT_PTR OSVR_TimeValue *tv) + OSVR_FUNC_NONNULL((1)); + +/** @brief Sums two time values, replacing the first with the result. + + @param tvA Destination and first source. + @param tvB second source + + If a given pointer is NULL, this function returns without doing anything. + + Both parameters are expected to be in normalized form. +*/ +OSVR_UTIL_EXPORT void osvrTimeValueSum(OSVR_INOUT_PTR OSVR_TimeValue *tvA, + OSVR_IN_PTR const OSVR_TimeValue *tvB) + OSVR_FUNC_NONNULL((1, 2)); + +/** @brief Computes the difference between two time values, replacing the first + with the result. + + Effectively, `*tvA = *tvA - *tvB` + + @param tvA Destination and first source. + @param tvB second source + + If a given pointer is NULL, this function returns without doing anything. + + Both parameters are expected to be in normalized form. +*/ +OSVR_UTIL_EXPORT void +osvrTimeValueDifference(OSVR_INOUT_PTR OSVR_TimeValue *tvA, + OSVR_IN_PTR const OSVR_TimeValue *tvB) + OSVR_FUNC_NONNULL((1, 2)); + +/** @brief Compares two time values (assumed to be normalized), returning + the same values as strcmp + + @return <0 if A is earlier than B, 0 if they are the same, and >0 if A + is later than B. +*/ +OSVR_UTIL_EXPORT int osvrTimeValueCmp(OSVR_IN_PTR const OSVR_TimeValue *tvA, + OSVR_IN_PTR const OSVR_TimeValue *tvB) + OSVR_FUNC_NONNULL((1, 2)); + +OSVR_EXTERN_C_END + +/** @brief Compute the difference between the two time values, returning the + duration as a double-precision floating-point number of seconds. + + Effectively, `ret = *tvA - *tvB` + + @param tvA first source. + @param tvB second source + @return Duration of timespan in seconds (floating-point) +*/ +OSVR_INLINE double +osvrTimeValueDurationSeconds(OSVR_IN_PTR const OSVR_TimeValue *tvA, + OSVR_IN_PTR const OSVR_TimeValue *tvB) { + OSVR_TimeValue A = *tvA; + osvrTimeValueDifference(&A, tvB); + double dt = A.seconds + A.microseconds / 1000000.0; + return dt; +} + +/** @brief True if A is later than B */ +OSVR_INLINE OSVR_CBool +osvrTimeValueGreater(OSVR_IN_PTR const OSVR_TimeValue *tvA, + OSVR_IN_PTR const OSVR_TimeValue *tvB) { + if (!tvA || !tvB) { + return OSVR_FALSE; + } + return ((tvA->seconds > tvB->seconds) || + (tvA->seconds == tvB->seconds && + tvA->microseconds > tvB->microseconds)) + ? OSVR_TRUE + : OSVR_FALSE; +} + +#ifdef __cplusplus + +#include <cmath> +#include <cassert> + +/// Returns true if the time value is normalized. Typically used in assertions. +inline bool osvrTimeValueIsNormalized(const OSVR_TimeValue &tv) { +#ifdef __APPLE__ + // apparently standard library used on mac only has floating-point abs? + return std::abs(double(tv.microseconds)) < 1000000 && +#else + return std::abs(tv.microseconds) < 1000000 && +#endif + ((tv.seconds > 0) == (tv.microseconds > 0)); +} + +/// True if A is later than B +inline bool osvrTimeValueGreater(const OSVR_TimeValue &tvA, + const OSVR_TimeValue &tvB) { + assert(osvrTimeValueIsNormalized(tvA) && + "First timevalue argument to comparison was not normalized!"); + assert(osvrTimeValueIsNormalized(tvB) && + "Second timevalue argument to comparison was not normalized!"); + return (tvA.seconds > tvB.seconds) || + (tvA.seconds == tvB.seconds && tvA.microseconds > tvB.microseconds); +} + +/// Operator > overload for time values +inline bool operator>(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { + return osvrTimeValueGreater(tvA, tvB); +} + +/// Operator < overload for time values +inline bool operator<(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { + // Change the order of arguments before forwarding. + return osvrTimeValueGreater(tvB, tvA); +} + +/// Operator == overload for time values +inline bool operator==(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { + assert( + osvrTimeValueIsNormalized(tvA) && + "First timevalue argument to equality comparison was not normalized!"); + assert( + osvrTimeValueIsNormalized(tvB) && + "Second timevalue argument to equality comparison was not normalized!"); + return (tvA.seconds == tvB.seconds) && + (tvA.microseconds == tvB.microseconds); +} +/// Operator == overload for time values +inline bool operator!=(const OSVR_TimeValue &tvA, const OSVR_TimeValue &tvB) { + assert(osvrTimeValueIsNormalized(tvA) && "First timevalue argument to " + "inequality comparison was not " + "normalized!"); + assert(osvrTimeValueIsNormalized(tvB) && "Second timevalue argument to " + "inequality comparison was not " + "normalized!"); + return (tvA.seconds != tvB.seconds) || + (tvA.microseconds != tvB.microseconds); +} +#endif + +/** @} */ + +#endif |