tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TimeValueC.h (9048B)


      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 osvrTimeValueToStructTimeval(
    104    OSVR_OUT struct timeval* dest, OSVR_IN_PTR const OSVR_TimeValue* src)
    105    OSVR_FUNC_NONNULL((1, 2));
    106 
    107 /** @brief Converts from a TimeValue struct to your system's struct timeval.
    108    @param dest An OSVR_TimeValue destination pointer.
    109    @param src Pointer to a struct timeval you'd like to convert from.
    110 
    111    The result is normalized.
    112 
    113    If either parameter is NULL, the function will return without doing
    114   anything.
    115 */
    116 OSVR_UTIL_EXPORT void osvrStructTimevalToTimeValue(
    117    OSVR_OUT OSVR_TimeValue* dest, OSVR_IN_PTR const struct timeval* src)
    118    OSVR_FUNC_NONNULL((1, 2));
    119 #endif
    120 
    121 /** @brief "Normalizes" a time value so that the absolute number of microseconds
    122    is less than 1,000,000, and that the sign of both components is the same.
    123 
    124    @param tv Address of a struct TimeValue to normalize in place.
    125 
    126    If the given pointer is NULL, this function returns without doing anything.
    127 */
    128 OSVR_UTIL_EXPORT void osvrTimeValueNormalize(OSVR_INOUT_PTR OSVR_TimeValue* tv)
    129    OSVR_FUNC_NONNULL((1));
    130 
    131 /** @brief Sums two time values, replacing the first with the result.
    132 
    133    @param tvA Destination and first source.
    134    @param tvB second source
    135 
    136    If a given pointer is NULL, this function returns without doing anything.
    137 
    138    Both parameters are expected to be in normalized form.
    139 */
    140 OSVR_UTIL_EXPORT void osvrTimeValueSum(OSVR_INOUT_PTR OSVR_TimeValue* tvA,
    141                                       OSVR_IN_PTR const OSVR_TimeValue* tvB)
    142    OSVR_FUNC_NONNULL((1, 2));
    143 
    144 /** @brief Computes the difference between two time values, replacing the first
    145    with the result.
    146 
    147    Effectively, `*tvA = *tvA - *tvB`
    148 
    149    @param tvA Destination and first source.
    150    @param tvB second source
    151 
    152    If a given pointer is NULL, this function returns without doing anything.
    153 
    154    Both parameters are expected to be in normalized form.
    155 */
    156 OSVR_UTIL_EXPORT void osvrTimeValueDifference(
    157    OSVR_INOUT_PTR OSVR_TimeValue* tvA, OSVR_IN_PTR const OSVR_TimeValue* tvB)
    158    OSVR_FUNC_NONNULL((1, 2));
    159 
    160 /** @brief  Compares two time values (assumed to be normalized), returning
    161    the same values as strcmp
    162 
    163    @return <0 if A is earlier than B, 0 if they are the same, and >0 if A
    164    is later than B.
    165 */
    166 OSVR_UTIL_EXPORT int osvrTimeValueCmp(OSVR_IN_PTR const OSVR_TimeValue* tvA,
    167                                      OSVR_IN_PTR const OSVR_TimeValue* tvB)
    168    OSVR_FUNC_NONNULL((1, 2));
    169 
    170 OSVR_EXTERN_C_END
    171 
    172 /** @brief Compute the difference between the two time values, returning the
    173    duration as a double-precision floating-point number of seconds.
    174 
    175    Effectively, `ret = *tvA - *tvB`
    176 
    177    @param tvA first source.
    178    @param tvB second source
    179    @return Duration of timespan in seconds (floating-point)
    180 */
    181 OSVR_INLINE double osvrTimeValueDurationSeconds(
    182    OSVR_IN_PTR const OSVR_TimeValue* tvA,
    183    OSVR_IN_PTR const OSVR_TimeValue* tvB) {
    184  OSVR_TimeValue A = *tvA;
    185  osvrTimeValueDifference(&A, tvB);
    186  double dt = A.seconds + A.microseconds / 1000000.0;
    187  return dt;
    188 }
    189 
    190 /** @brief True if A is later than B */
    191 OSVR_INLINE OSVR_CBool
    192 osvrTimeValueGreater(OSVR_IN_PTR const OSVR_TimeValue* tvA,
    193                     OSVR_IN_PTR const OSVR_TimeValue* tvB) {
    194  if (!tvA || !tvB) {
    195    return OSVR_FALSE;
    196  }
    197  return ((tvA->seconds > tvB->seconds) ||
    198          (tvA->seconds == tvB->seconds &&
    199           tvA->microseconds > tvB->microseconds))
    200             ? OSVR_TRUE
    201             : OSVR_FALSE;
    202 }
    203 
    204 #ifdef __cplusplus
    205 
    206 #  include <cmath>
    207 #  include <cassert>
    208 
    209 /// Returns true if the time value is normalized. Typically used in assertions.
    210 inline bool osvrTimeValueIsNormalized(const OSVR_TimeValue& tv) {
    211 #  ifdef __APPLE__
    212  // apparently standard library used on mac only has floating-point abs?
    213  return std::abs(double(tv.microseconds)) < 1000000 &&
    214 #  else
    215  return std::abs(tv.microseconds) < 1000000 &&
    216 #  endif
    217         ((tv.seconds > 0) == (tv.microseconds > 0));
    218 }
    219 
    220 /// True if A is later than B
    221 inline bool osvrTimeValueGreater(const OSVR_TimeValue& tvA,
    222                                 const OSVR_TimeValue& tvB) {
    223  assert(osvrTimeValueIsNormalized(tvA) &&
    224         "First timevalue argument to comparison was not normalized!");
    225  assert(osvrTimeValueIsNormalized(tvB) &&
    226         "Second timevalue argument to comparison was not normalized!");
    227  return (tvA.seconds > tvB.seconds) ||
    228         (tvA.seconds == tvB.seconds && tvA.microseconds > tvB.microseconds);
    229 }
    230 
    231 /// Operator > overload for time values
    232 inline bool operator>(const OSVR_TimeValue& tvA, const OSVR_TimeValue& tvB) {
    233  return osvrTimeValueGreater(tvA, tvB);
    234 }
    235 
    236 /// Operator < overload for time values
    237 inline bool operator<(const OSVR_TimeValue& tvA, const OSVR_TimeValue& tvB) {
    238  // Change the order of arguments before forwarding.
    239  return osvrTimeValueGreater(tvB, tvA);
    240 }
    241 
    242 /// Operator == overload for time values
    243 inline bool operator==(const OSVR_TimeValue& tvA, const OSVR_TimeValue& tvB) {
    244  assert(osvrTimeValueIsNormalized(tvA) &&
    245         "First timevalue argument to equality comparison was not normalized!");
    246  assert(
    247      osvrTimeValueIsNormalized(tvB) &&
    248      "Second timevalue argument to equality comparison was not normalized!");
    249  return (tvA.seconds == tvB.seconds) && (tvA.microseconds == tvB.microseconds);
    250 }
    251 /// Operator == overload for time values
    252 inline bool operator!=(const OSVR_TimeValue& tvA, const OSVR_TimeValue& tvB) {
    253  assert(osvrTimeValueIsNormalized(tvA) &&
    254         "First timevalue argument to "
    255         "inequality comparison was not "
    256         "normalized!");
    257  assert(osvrTimeValueIsNormalized(tvB) &&
    258         "Second timevalue argument to "
    259         "inequality comparison was not "
    260         "normalized!");
    261  return (tvA.seconds != tvB.seconds) || (tvA.microseconds != tvB.microseconds);
    262 }
    263 #endif
    264 
    265 /** @} */
    266 
    267 #endif