tor-browser

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

TimeStamp.h (20732B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef mozilla_TimeStamp_h
      8 #define mozilla_TimeStamp_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/Attributes.h"
     12 #include "mozilla/FloatingPoint.h"
     13 #include "mozilla/Types.h"
     14 #include <algorithm>  // for std::min, std::max
     15 #include <ostream>
     16 #include <stdint.h>
     17 #include <type_traits>
     18 
     19 namespace IPC {
     20 template <typename T>
     21 struct ParamTraits;
     22 }  // namespace IPC
     23 
     24 namespace mozilla {
     25 
     26 using TimeStampValue = uint64_t;
     27 
     28 class TimeStamp;
     29 class TimeStampTests;
     30 
     31 /**
     32 * Platform-specific implementation details of BaseTimeDuration.
     33 */
     34 class BaseTimeDurationPlatformUtils {
     35 public:
     36  static MFBT_API double ToSeconds(int64_t aTicks);
     37  static MFBT_API int64_t TicksFromMilliseconds(double aMilliseconds);
     38 };
     39 
     40 /**
     41 * Instances of this class represent the length of an interval of time.
     42 * Negative durations are allowed, meaning the end is before the start.
     43 *
     44 * Internally the duration is stored as a system-dependent unit.
     45 *
     46 * The ValueCalculator template parameter determines how arithmetic
     47 * operations are performed on the integer count of ticks (mValue).
     48 */
     49 template <typename ValueCalculator>
     50 class BaseTimeDuration {
     51 public:
     52  // The default duration is 0.
     53  constexpr BaseTimeDuration() : mValue(0) {}
     54  // Allow construction using '0' as the initial value, for readability,
     55  // but no other numbers (so we don't have any implicit unit conversions).
     56  struct _SomethingVeryRandomHere;
     57  MOZ_IMPLICIT BaseTimeDuration(_SomethingVeryRandomHere* aZero) : mValue(0) {
     58    MOZ_ASSERT(!aZero, "Who's playing funny games here?");
     59  }
     60  // Default copy-constructor and assignment are OK
     61 
     62  // Converting copy-constructor and assignment operator
     63  template <typename E>
     64  explicit BaseTimeDuration(const BaseTimeDuration<E>& aOther)
     65      : mValue(aOther.mValue) {}
     66 
     67  template <typename E>
     68  BaseTimeDuration& operator=(const BaseTimeDuration<E>& aOther) {
     69    mValue = aOther.mValue;
     70    return *this;
     71  }
     72 
     73  // ToSeconds returns the (fractional) number of seconds of the duration
     74  // with the maximum representable precision.
     75  double ToSeconds() const {
     76    if (mValue == INT64_MAX) {
     77      return PositiveInfinity<double>();
     78    }
     79    if (mValue == INT64_MIN) {
     80      return NegativeInfinity<double>();
     81    }
     82    return BaseTimeDurationPlatformUtils::ToSeconds(mValue);
     83  }
     84  // ToMilliseconds returns the (fractional) number of milliseconds of the
     85  // duration with the maximum representable precision.
     86  double ToMilliseconds() const { return ToSeconds() * 1000.0; }
     87  // ToMicroseconds returns the (fractional) number of microseconds of the
     88  // duration with the maximum representable precision.
     89  double ToMicroseconds() const { return ToMilliseconds() * 1000.0; }
     90 
     91  // Using a double here is safe enough; with 53 bits we can represent
     92  // durations up to over 280,000 years exactly.  If the units of
     93  // mValue do not allow us to represent durations of that length,
     94  // long durations are clamped to the max/min representable value
     95  // instead of overflowing.
     96  static inline BaseTimeDuration FromSeconds(double aSeconds) {
     97    return FromMilliseconds(aSeconds * 1000.0);
     98  }
     99  static BaseTimeDuration FromMilliseconds(double aMilliseconds) {
    100    if (aMilliseconds == PositiveInfinity<double>()) {
    101      return Forever();
    102    }
    103    if (aMilliseconds == NegativeInfinity<double>()) {
    104      return FromTicks(INT64_MIN);
    105    }
    106    return FromTicks(
    107        BaseTimeDurationPlatformUtils::TicksFromMilliseconds(aMilliseconds));
    108  }
    109  static inline BaseTimeDuration FromMicroseconds(double aMicroseconds) {
    110    return FromMilliseconds(aMicroseconds / 1000.0);
    111  }
    112 
    113  static constexpr BaseTimeDuration Zero() { return BaseTimeDuration(); }
    114  static constexpr BaseTimeDuration Forever() { return FromTicks(INT64_MAX); }
    115 
    116  BaseTimeDuration operator+(const BaseTimeDuration& aOther) const {
    117    return FromTicks(ValueCalculator::Add(mValue, aOther.mValue));
    118  }
    119  BaseTimeDuration operator-(const BaseTimeDuration& aOther) const {
    120    return FromTicks(ValueCalculator::Subtract(mValue, aOther.mValue));
    121  }
    122  BaseTimeDuration& operator+=(const BaseTimeDuration& aOther) {
    123    mValue = ValueCalculator::Add(mValue, aOther.mValue);
    124    return *this;
    125  }
    126  BaseTimeDuration& operator-=(const BaseTimeDuration& aOther) {
    127    mValue = ValueCalculator::Subtract(mValue, aOther.mValue);
    128    return *this;
    129  }
    130  BaseTimeDuration operator-() const {
    131    // We don't just use FromTicks(ValueCalculator::Subtract(0, mValue))
    132    // since that won't give the correct result for -TimeDuration::Forever().
    133    int64_t ticks;
    134    if (mValue == INT64_MAX) {
    135      ticks = INT64_MIN;
    136    } else if (mValue == INT64_MIN) {
    137      ticks = INT64_MAX;
    138    } else {
    139      ticks = -mValue;
    140    }
    141 
    142    return FromTicks(ticks);
    143  }
    144 
    145  static BaseTimeDuration Max(const BaseTimeDuration& aA,
    146                              const BaseTimeDuration& aB) {
    147    return FromTicks(std::max(aA.mValue, aB.mValue));
    148  }
    149  static BaseTimeDuration Min(const BaseTimeDuration& aA,
    150                              const BaseTimeDuration& aB) {
    151    return FromTicks(std::min(aA.mValue, aB.mValue));
    152  }
    153 
    154 private:
    155  // Block double multiplier (slower, imprecise if long duration) - Bug 853398.
    156  // If required, use MultDouble explicitly and with care.
    157  BaseTimeDuration operator*(const double aMultiplier) const = delete;
    158 
    159  // Block double divisor (for the same reason, and because dividing by
    160  // fractional values would otherwise invoke the int64_t variant, and rounding
    161  // the passed argument can then cause divide-by-zero) - Bug 1147491.
    162  BaseTimeDuration operator/(const double aDivisor) const = delete;
    163 
    164 public:
    165  BaseTimeDuration MultDouble(double aMultiplier) const {
    166    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
    167  }
    168  BaseTimeDuration operator*(const int32_t aMultiplier) const {
    169    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
    170  }
    171  BaseTimeDuration operator*(const uint32_t aMultiplier) const {
    172    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
    173  }
    174  BaseTimeDuration operator*(const int64_t aMultiplier) const {
    175    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
    176  }
    177  BaseTimeDuration operator*(const uint64_t aMultiplier) const {
    178    if (aMultiplier > INT64_MAX) {
    179      return Forever();
    180    }
    181    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
    182  }
    183  BaseTimeDuration operator/(const int64_t aDivisor) const {
    184    MOZ_ASSERT(aDivisor != 0, "Division by zero");
    185    return FromTicks(ValueCalculator::Divide(mValue, aDivisor));
    186  }
    187  double operator/(const BaseTimeDuration& aOther) const {
    188    MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
    189    return ValueCalculator::DivideDouble(mValue, aOther.mValue);
    190  }
    191  BaseTimeDuration operator%(const BaseTimeDuration& aOther) const {
    192    MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
    193    return FromTicks(ValueCalculator::Modulo(mValue, aOther.mValue));
    194  }
    195 
    196  template <typename E>
    197  bool operator<(const BaseTimeDuration<E>& aOther) const {
    198    return mValue < aOther.mValue;
    199  }
    200  template <typename E>
    201  bool operator<=(const BaseTimeDuration<E>& aOther) const {
    202    return mValue <= aOther.mValue;
    203  }
    204  template <typename E>
    205  bool operator>=(const BaseTimeDuration<E>& aOther) const {
    206    return mValue >= aOther.mValue;
    207  }
    208  template <typename E>
    209  bool operator>(const BaseTimeDuration<E>& aOther) const {
    210    return mValue > aOther.mValue;
    211  }
    212  template <typename E>
    213  bool operator==(const BaseTimeDuration<E>& aOther) const {
    214    return mValue == aOther.mValue;
    215  }
    216  template <typename E>
    217  bool operator!=(const BaseTimeDuration<E>& aOther) const {
    218    return mValue != aOther.mValue;
    219  }
    220  bool IsZero() const { return mValue == 0; }
    221  explicit operator bool() const { return mValue != 0; }
    222 
    223  friend std::ostream& operator<<(std::ostream& aStream,
    224                                  const BaseTimeDuration& aDuration) {
    225    return aStream << aDuration.ToMilliseconds() << " ms";
    226  }
    227 
    228  // We could define additional operators here:
    229  // -- convert to/from other time units
    230  // -- scale duration by a float
    231  // but let's do that on demand.
    232  // Comparing durations for equality will only lead to bugs on
    233  // platforms with high-resolution timers.
    234 
    235 private:
    236  friend class TimeStamp;
    237  friend struct IPC::ParamTraits<mozilla::BaseTimeDuration<ValueCalculator>>;
    238  template <typename>
    239  friend class BaseTimeDuration;
    240 
    241  static constexpr BaseTimeDuration FromTicks(int64_t aTicks) {
    242    BaseTimeDuration t;
    243    t.mValue = aTicks;
    244    return t;
    245  }
    246 
    247  static BaseTimeDuration FromTicks(double aTicks) {
    248    // NOTE: this MUST be a >= test, because int64_t(double(INT64_MAX))
    249    // overflows and gives INT64_MIN.
    250    if (aTicks >= double(INT64_MAX)) {
    251      return FromTicks(INT64_MAX);
    252    }
    253 
    254    // This MUST be a <= test.
    255    if (aTicks <= double(INT64_MIN)) {
    256      return FromTicks(INT64_MIN);
    257    }
    258 
    259    return FromTicks(int64_t(aTicks));
    260  }
    261 
    262  // Duration, result is implementation-specific difference of two TimeStamps
    263  int64_t mValue;
    264 };
    265 
    266 /**
    267 * Perform arithmetic operations on the value of a BaseTimeDuration without
    268 * doing strict checks on the range of values.
    269 */
    270 class TimeDurationValueCalculator {
    271 public:
    272  static int64_t Add(int64_t aA, int64_t aB) { return aA + aB; }
    273  static int64_t Subtract(int64_t aA, int64_t aB) { return aA - aB; }
    274 
    275  template <typename T>
    276  static int64_t Multiply(int64_t aA, T aB) {
    277    static_assert(std::is_integral_v<T>,
    278                  "Using integer multiplication routine with non-integer type."
    279                  " Further specialization required");
    280    return aA * static_cast<int64_t>(aB);
    281  }
    282 
    283  static int64_t Divide(int64_t aA, int64_t aB) { return aA / aB; }
    284  static double DivideDouble(int64_t aA, int64_t aB) {
    285    return static_cast<double>(aA) / aB;
    286  }
    287  static int64_t Modulo(int64_t aA, int64_t aB) { return aA % aB; }
    288 };
    289 
    290 template <>
    291 inline int64_t TimeDurationValueCalculator::Multiply<double>(int64_t aA,
    292                                                             double aB) {
    293  return static_cast<int64_t>(aA * aB);
    294 }
    295 
    296 /**
    297 * Specialization of BaseTimeDuration that uses TimeDurationValueCalculator for
    298 * arithmetic on the mValue member.
    299 *
    300 * Use this class for time durations that are *not* expected to hold values of
    301 * Forever (or the negative equivalent) or when such time duration are *not*
    302 * expected to be used in arithmetic operations.
    303 */
    304 typedef BaseTimeDuration<TimeDurationValueCalculator> TimeDuration;
    305 
    306 /**
    307 * Instances of this class represent moments in time, or a special
    308 * "null" moment. We do not use the non-monotonic system clock or
    309 * local time, since they can be reset, causing apparent backward
    310 * travel in time, which can confuse algorithms. Instead we measure
    311 * elapsed time according to the system.  This time can never go
    312 * backwards (i.e. it never wraps around, at least not in less than
    313 * five million years of system elapsed time). It might not advance
    314 * while the system is sleeping. If TimeStamp::SetNow() is not called
    315 * at all for hours or days, we might not notice the passage of some
    316 * of that time.
    317 *
    318 * We deliberately do not expose a way to convert TimeStamps to some
    319 * particular unit. All you can do is compute a difference between two
    320 * TimeStamps to get a TimeDuration. You can also add a TimeDuration
    321 * to a TimeStamp to get a new TimeStamp. You can't do something
    322 * meaningless like add two TimeStamps.
    323 *
    324 * Internally this is implemented as a wrapper around high-resolution,
    325 * monotonic, platform-dependent system clocks.
    326 *
    327 * This class is similar to C++11's time_point, however it is
    328 * explicitly nullable and provides an IsNull() method. time_point
    329 * is initialized to the clock's epoch and provides a
    330 * time_since_epoch() method that functions similiarly. i.e.
    331 * t.IsNull() is equivalent to t.time_since_epoch() ==
    332 * decltype(t)::duration::zero();
    333 *
    334 * Note that, since TimeStamp objects are small, prefer to pass them by value
    335 * unless there is a specific reason not to do so.
    336 */
    337 class TimeStamp {
    338 public:
    339  using DurationType = TimeDuration;
    340  /**
    341   * Initialize to the "null" moment
    342   */
    343  constexpr TimeStamp() : mValue(0) {}
    344  // Default copy-constructor and assignment are OK
    345 
    346  /**
    347   * The system timestamps are the same as the TimeStamp
    348   * retrieved by mozilla::TimeStamp. Since we need this for
    349   * vsync timestamps, we enable the creation of mozilla::TimeStamps
    350   * on platforms that support vsync aligned refresh drivers / compositors
    351   * Verified true as of Jan 31, 2015: B2G and OS X
    352   * False on Windows 7
    353   * Android's event time uses CLOCK_MONOTONIC via SystemClock.uptimeMilles.
    354   * So it is same value of TimeStamp posix implementation.
    355   * Wayland/GTK event time also uses CLOCK_MONOTONIC on Weston/Mutter
    356   * compositors.
    357   * UNTESTED ON OTHER PLATFORMS
    358   */
    359 #if defined(XP_DARWIN) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK)
    360  static TimeStamp FromSystemTime(int64_t aSystemTime) {
    361    static_assert(sizeof(aSystemTime) == sizeof(TimeStampValue),
    362                  "System timestamp should be same units as TimeStampValue");
    363    return TimeStamp(aSystemTime);
    364  }
    365 #endif
    366 
    367  /**
    368   * Return true if this is the "null" moment
    369   */
    370  constexpr bool IsNull() const { return mValue == 0; }
    371 
    372  /**
    373   * Return true if this is not the "null" moment, may be used in tests, e.g.:
    374   * |if (timestamp) { ... }|
    375   */
    376  explicit operator bool() const { return mValue != 0; }
    377 
    378  /**
    379   * Return a timestamp reflecting the current elapsed system time. This
    380   * is monotonically increasing (i.e., does not decrease) over the
    381   * lifetime of this process' XPCOM session.
    382   *
    383   * Now() is trying to ensure the best possible precision on each platform,
    384   * at least one millisecond.
    385   */
    386  static TimeStamp Now() { return Now(true); }
    387 
    388  /**
    389   * Return a (coarse) timestamp reflecting the current elapsed system time.
    390   * NowLoRes() behaves different depending on the OS:
    391   *
    392   * Windows: NowLoRes() == Now(), uses always QueryPerformanceCounter.
    393   * MacOS:   NowLoRes() == Now(), uses always mach_absolute_time.
    394   * Posix:   If the kernel supports CLOCK_MONOTONIC_COARSE use that,
    395   *          CLOCK_MONOTONIC otherwise.
    396   *
    397   * Used to promise better performance, which might still be true only for
    398   * Posix.
    399   */
    400  static TimeStamp NowLoRes() { return Now(false); }
    401 
    402  /**
    403   * Return a timestamp representing the time when the current process was
    404   * created which will be comparable with other timestamps taken with this
    405   * class.
    406   *
    407   * @returns A timestamp representing the time when the process was created
    408   */
    409  static MFBT_API TimeStamp ProcessCreation();
    410 
    411  /**
    412   * Return the very first timestamp that was taken. This can be used instead
    413   * of TimeStamp::ProcessCreation() by code that might not allow running the
    414   * complex logic required to compute the real process creation. This will
    415   * necessarily have been recorded sometimes after TimeStamp::ProcessCreation()
    416   * or at best should be equal to it.
    417   *
    418   * @returns The first tiemstamp that was taken by this process
    419   */
    420  static MFBT_API TimeStamp FirstTimeStamp();
    421 
    422  /**
    423   * Records a process restart. After this call ProcessCreation() will return
    424   * the time when the browser was restarted instead of the actual time when
    425   * the process was created.
    426   */
    427  static MFBT_API void RecordProcessRestart();
    428 
    429 #ifdef XP_LINUX
    430  uint64_t RawClockMonotonicNanosecondsSinceBoot() const {
    431    return static_cast<uint64_t>(mValue);
    432  }
    433 #endif
    434 
    435 #ifdef XP_DARWIN
    436  // Returns the number of nanoseconds since the mach_absolute_time origin.
    437  MFBT_API uint64_t RawMachAbsoluteTimeNanoseconds() const;
    438 #endif
    439 
    440 #ifdef XP_WIN
    441  uint64_t RawQueryPerformanceCounterValue() const {
    442    return static_cast<uint64_t>(mValue);
    443  }
    444 #endif
    445 
    446  /**
    447   * Compute the difference between two timestamps. Both must be non-null.
    448   */
    449  TimeDuration operator-(const TimeStamp& aOther) const {
    450    MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
    451    MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
    452    static_assert(-INT64_MAX > INT64_MIN, "int64_t sanity check");
    453    int64_t ticks = int64_t(mValue - aOther.mValue);
    454    // Check for overflow.
    455    if (mValue > aOther.mValue) {
    456      if (ticks < 0) {
    457        ticks = INT64_MAX;
    458      }
    459    } else {
    460      if (ticks > 0) {
    461        ticks = INT64_MIN;
    462      }
    463    }
    464    return TimeDuration::FromTicks(ticks);
    465  }
    466 
    467  TimeStamp operator+(const TimeDuration& aOther) const {
    468    TimeStamp result = *this;
    469    result += aOther;
    470    return result;
    471  }
    472  TimeStamp operator-(const TimeDuration& aOther) const {
    473    TimeStamp result = *this;
    474    result -= aOther;
    475    return result;
    476  }
    477  TimeStamp& operator+=(const TimeDuration& aOther) {
    478    MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
    479    TimeStampValue value = mValue + aOther.mValue;
    480    // Check for underflow.
    481    // (We don't check for overflow because it's not obvious what the error
    482    //  behavior should be in that case.)
    483    if (aOther.mValue < 0 && value > mValue) {
    484      value = 0;
    485    }
    486    mValue = value;
    487    return *this;
    488  }
    489  TimeStamp& operator-=(const TimeDuration& aOther) {
    490    MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
    491    TimeStampValue value = mValue - aOther.mValue;
    492    // Check for underflow.
    493    // (We don't check for overflow because it's not obvious what the error
    494    //  behavior should be in that case.)
    495    if (aOther.mValue > 0 && value > mValue) {
    496      value = 0;
    497    }
    498    mValue = value;
    499    return *this;
    500  }
    501 
    502  constexpr bool operator<(const TimeStamp& aOther) const {
    503    MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
    504    MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
    505    return mValue < aOther.mValue;
    506  }
    507  constexpr bool operator<=(const TimeStamp& aOther) const {
    508    MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
    509    MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
    510    return mValue <= aOther.mValue;
    511  }
    512  constexpr bool operator>=(const TimeStamp& aOther) const {
    513    MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
    514    MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
    515    return mValue >= aOther.mValue;
    516  }
    517  constexpr bool operator>(const TimeStamp& aOther) const {
    518    MOZ_ASSERT(!IsNull(), "Cannot compute with a null value");
    519    MOZ_ASSERT(!aOther.IsNull(), "Cannot compute with aOther null value");
    520    return mValue > aOther.mValue;
    521  }
    522  bool operator==(const TimeStamp& aOther) const {
    523    return IsNull() ? aOther.IsNull()
    524                    : !aOther.IsNull() && mValue == aOther.mValue;
    525  }
    526  bool operator!=(const TimeStamp& aOther) const { return !(*this == aOther); }
    527 
    528  // Comparing TimeStamps for equality should be discouraged. Adding
    529  // two TimeStamps, or scaling TimeStamps, is nonsense and must never
    530  // be allowed.
    531 
    532  static MFBT_API void Startup();
    533  static MFBT_API void Shutdown();
    534 
    535 #if defined(DEBUG)
    536  TimeStampValue GetValue() const { return mValue; }
    537 #endif
    538 
    539 private:
    540  friend struct IPC::ParamTraits<mozilla::TimeStamp>;
    541  friend struct TimeStampInitialization;
    542  friend class TimeStampTests;
    543 
    544  constexpr MOZ_IMPLICIT TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
    545 
    546  static MFBT_API TimeStamp Now(bool aHighResolution);
    547 
    548  /**
    549   * Computes the uptime of the current process in microseconds. The result
    550   * is platform-dependent and needs to be checked against existing timestamps
    551   * for consistency.
    552   *
    553   * @returns The number of microseconds since the calling process was started
    554   *          or 0 if an error was encountered while computing the uptime
    555   */
    556  static MFBT_API uint64_t ComputeProcessUptime();
    557 
    558  /**
    559   * When built with PRIntervalTime, a value of 0 means this instance
    560   * is "null". Otherwise, the low 32 bits represent a PRIntervalTime,
    561   * and the high 32 bits represent a counter of the number of
    562   * rollovers of PRIntervalTime that we've seen. This counter starts
    563   * at 1 to avoid a real time colliding with the "null" value.
    564   *
    565   * PR_INTERVAL_MAX is set at 100,000 ticks per second. So the minimum
    566   * time to wrap around is about 2^64/100000 seconds, i.e. about
    567   * 5,849,424 years.
    568   *
    569   * When using a system clock, a value is system dependent.
    570   */
    571  TimeStampValue mValue;
    572 };
    573 
    574 }  // namespace mozilla
    575 
    576 #endif /* mozilla_TimeStamp_h */