// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // `Time` represents an absolute point in coordinated universal time (UTC), // internally represented as microseconds (s/1,000,000) since the Windows epoch // (1601-01-01 00:00:00 UTC). System-dependent clock interface routines are // defined in time_PLATFORM.cc. Note that values for `Time` may skew and jump // around as the operating system makes adjustments to synchronize (e.g., with // NTP servers). Thus, client code that uses the `Time` class must account for // this. // // `TimeDelta` represents a duration of time, internally represented in // microseconds. // // `TimeTicks` and `ThreadTicks` represent an abstract time that is most of the // time incrementing, for use in measuring time durations. Internally, they are // represented in microseconds. They cannot be converted to a human-readable // time, but are guaranteed not to decrease (unlike the `Time` class). Note // that `TimeTicks` may "stand still" (e.g., if the computer is suspended), and // `ThreadTicks` will "stand still" whenever the thread has been de-scheduled // by the operating system. // // All time classes are copyable, assignable, and occupy 64 bits per instance. // Prefer to pass them by value, e.g.: // // void MyFunction(TimeDelta arg); // // All time classes support `operator<<` with logging streams, e.g. `LOG(INFO)`. // For human-readable formatting, use //base/i18n/time_formatting.h. // // Example use cases for different time classes: // // Time: Interpreting the wall-clock time provided by a remote system. // Detecting whether cached resources have expired. Providing the // user with a display of the current date and time. Determining // the amount of time between events across re-boots of the // machine. // // TimeTicks: Tracking the amount of time a task runs. Executing delayed // tasks at the right time. Computing presentation timestamps. // Synchronizing audio and video using TimeTicks as a common // reference clock (lip-sync). Measuring network round-trip // latency. // // ThreadTicks: Benchmarking how long the current thread has been doing actual // work. // // Serialization: // // Use the helpers in //base/json/values_util.h when serializing `Time` // or `TimeDelta` to/from `base::Value`. // // Otherwise: // // - Time: use `FromDeltaSinceWindowsEpoch()`/`ToDeltaSinceWindowsEpoch()`. // - TimeDelta: use `base::Microseconds()`/`InMicroseconds()`. // // `TimeTicks` and `ThreadTicks` do not have a stable origin; serialization for // the purpose of persistence is not supported. #ifndef BASE_TIME_TIME_H_ #define BASE_TIME_TIME_H_ #include #include #include #include #include #include #include #include #include "base/base_export.h" #include "base/check.h" #include "base/check_op.h" #include "base/compiler_specific.h" #include "base/numerics/clamped_math.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #if BUILDFLAG(IS_FUCHSIA) #include #endif #if BUILDFLAG(IS_APPLE) #include #include // Avoid Mac system header macro leak. #undef TYPE_BOOL #endif #if BUILDFLAG(IS_ANDROID) #include #endif #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #include #include #endif #if BUILDFLAG(IS_WIN) #include "base/gtest_prod_util.h" #include "base/win/windows_types.h" namespace ABI { namespace Windows { namespace Foundation { struct DateTime; struct TimeSpan; } // namespace Foundation } // namespace Windows } // namespace ABI #endif namespace base { #if BUILDFLAG(IS_WIN) class PlatformThreadHandle; #endif class TimeDelta; template constexpr TimeDelta Microseconds(T n); namespace { // TODO: Replace usage of this with std::isnan() once Chromium uses C++23, // where that is constexpr. constexpr bool isnan(double d) { return d != d; } } // TimeDelta ------------------------------------------------------------------ class BASE_EXPORT TimeDelta { public: constexpr TimeDelta() = default; #if BUILDFLAG(IS_WIN) static TimeDelta FromQPCValue(LONGLONG qpc_value); // TODO(crbug.com/989694): Avoid base::TimeDelta factory functions // based on absolute time static TimeDelta FromFileTime(FILETIME ft); static TimeDelta FromWinrtDateTime(ABI::Windows::Foundation::DateTime dt); static TimeDelta FromWinrtTimeSpan(ABI::Windows::Foundation::TimeSpan ts); #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) static TimeDelta FromTimeSpec(const timespec& ts); #endif #if BUILDFLAG(IS_FUCHSIA) static TimeDelta FromZxDuration(zx_duration_t nanos); #endif #if BUILDFLAG(IS_APPLE) static TimeDelta FromMachTime(uint64_t mach_time); #endif // BUILDFLAG(IS_APPLE) // Converts an integer value representing TimeDelta to a class. This is used // when deserializing a |TimeDelta| structure, using a value known to be // compatible. It is not provided as a constructor because the integer type // may be unclear from the perspective of a caller. // // DEPRECATED - Do not use in new code. http://crbug.com/634507 static constexpr TimeDelta FromInternalValue(int64_t delta) { return TimeDelta(delta); } // Returns the maximum time delta, which should be greater than any reasonable // time delta we might compare it to. If converted to double with ToDouble() // it becomes an IEEE double infinity. Use FiniteMax() if you want a very // large number that doesn't do this. TimeDelta math saturates at the end // points so adding to TimeDelta::Max() leaves the value unchanged. // Subtracting should leave the value unchanged but currently changes it // TODO(https://crbug.com/869387). static constexpr TimeDelta Max(); // Returns the minimum time delta, which should be less than than any // reasonable time delta we might compare it to. For more details see the // comments for Max(). static constexpr TimeDelta Min(); // Returns the maximum time delta which is not equivalent to infinity. Only // subtracting a finite time delta from this time delta has a defined result. static constexpr TimeDelta FiniteMax(); // Returns the minimum time delta which is not equivalent to -infinity. Only // adding a finite time delta to this time delta has a defined result. static constexpr TimeDelta FiniteMin(); // Returns the internal numeric value of the TimeDelta object. Please don't // use this and do arithmetic on it, as it is more error prone than using the // provided operators. // For serializing, use FromInternalValue to reconstitute. // // DEPRECATED - Do not use in new code. http://crbug.com/634507 constexpr int64_t ToInternalValue() const { return delta_; } // Returns the magnitude (absolute value) of this TimeDelta. constexpr TimeDelta magnitude() const { return TimeDelta(delta_.Abs()); } // Returns true if the time delta is a zero, positive or negative time delta. constexpr bool is_zero() const { return delta_ == 0; } constexpr bool is_positive() const { return delta_ > 0; } constexpr bool is_negative() const { return delta_ < 0; } // Returns true if the time delta is the maximum/minimum time delta. constexpr bool is_max() const { return *this == Max(); } constexpr bool is_min() const { return *this == Min(); } constexpr bool is_inf() const { return is_min() || is_max(); } #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) struct timespec ToTimeSpec() const; #endif #if BUILDFLAG(IS_FUCHSIA) zx_duration_t ToZxDuration() const; #endif #if BUILDFLAG(IS_WIN) ABI::Windows::Foundation::DateTime ToWinrtDateTime() const; ABI::Windows::Foundation::TimeSpan ToWinrtTimeSpan() const; #endif // Returns the frequency in Hertz (cycles per second) that has a period of // *this. constexpr double ToHz() const; // Returns the time delta in some unit. Minimum argument values return as // -inf for doubles and min type values otherwise. Maximum ones are treated as // +inf for doubles and max type values otherwise. Their results will produce // an is_min() or is_max() TimeDelta. The InXYZF versions return a floating // point value. The InXYZ versions return a truncated value (aka rounded // towards zero, std::trunc() behavior). The InXYZFloored() versions round to // lesser integers (std::floor() behavior). The XYZRoundedUp() versions round // up to greater integers (std::ceil() behavior). WARNING: Floating point // arithmetic is such that XXX(t.InXXXF()) may not precisely equal |t|. // Hence, floating point values should not be used for storage. constexpr int InDays() const; constexpr int InDaysFloored() const; constexpr int InHours() const; constexpr int InMinutes() const; constexpr double InSecondsF() const; constexpr int64_t InSeconds() const; constexpr int64_t InSecondsFloored() const; constexpr double InMillisecondsF() const; constexpr int64_t InMilliseconds() const; constexpr int64_t InMillisecondsRoundedUp() const; constexpr int64_t InMicroseconds() const { return delta_; } constexpr double InMicrosecondsF() const; constexpr int64_t InNanoseconds() const; // Computations with other deltas. constexpr TimeDelta operator+(TimeDelta other) const; constexpr TimeDelta operator-(TimeDelta other) const; constexpr TimeDelta& operator+=(TimeDelta other) { return *this = (*this + other); } constexpr TimeDelta& operator-=(TimeDelta other) { return *this = (*this - other); } constexpr TimeDelta operator-() const { if (!is_inf()) return TimeDelta(-delta_); return (delta_ < 0) ? Max() : Min(); } // Computations with numeric types. template constexpr TimeDelta operator*(T a) const { return TimeDelta(int64_t{delta_ * a}); } template constexpr TimeDelta operator/(T a) const { return TimeDelta(int64_t{delta_ / a}); } template constexpr TimeDelta& operator*=(T a) { return *this = (*this * a); } template constexpr TimeDelta& operator/=(T a) { return *this = (*this / a); } // This does floating-point division. For an integer result, either call // IntDiv(), or (possibly clearer) use this operator with // base::Clamp{Ceil,Floor,Round}() or base::saturated_cast() (for truncation). // Note that converting to double here drops precision to 53 bits. constexpr double operator/(TimeDelta a) const { // 0/0 and inf/inf (any combination of positive and negative) are invalid // (they are almost certainly not intentional, and result in NaN, which // turns into 0 if clamped to an integer; this makes introducing subtle bugs // too easy). CHECK(!is_zero() || !a.is_zero()); CHECK(!is_inf() || !a.is_inf()); return ToDouble() / a.ToDouble(); } constexpr int64_t IntDiv(TimeDelta a) const { if (!is_inf() && !a.is_zero()) return int64_t{delta_ / a.delta_}; // For consistency, use the same edge case CHECKs and behavior as the code // above. CHECK(!is_zero() || !a.is_zero()); CHECK(!is_inf() || !a.is_inf()); return ((delta_ < 0) == (a.delta_ < 0)) ? std::numeric_limits::max() : std::numeric_limits::min(); } constexpr TimeDelta operator%(TimeDelta a) const { return TimeDelta( (is_inf() || a.is_zero() || a.is_inf()) ? delta_ : (delta_ % a.delta_)); } constexpr TimeDelta& operator%=(TimeDelta other) { return *this = (*this % other); } // Comparison operators. friend constexpr bool operator==(TimeDelta, TimeDelta) = default; friend constexpr std::strong_ordering operator<=>(TimeDelta, TimeDelta) = default; // Returns this delta, ceiled/floored/rounded-away-from-zero to the nearest // multiple of |interval|. TimeDelta CeilToMultiple(TimeDelta interval) const; TimeDelta FloorToMultiple(TimeDelta interval) const; TimeDelta RoundToMultiple(TimeDelta interval) const; private: // Constructs a delta given the duration in microseconds. This is private // to avoid confusion by callers with an integer constructor. Use // base::Seconds, base::Milliseconds, etc. instead. constexpr explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} constexpr explicit TimeDelta(ClampedNumeric delta_us) : delta_(delta_us) {} // Returns a double representation of this TimeDelta's tick count. In // particular, Max()/Min() are converted to +/-infinity. constexpr double ToDouble() const { if (!is_inf()) return static_cast(delta_); return (delta_ < 0) ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); } // Delta in microseconds. ClampedNumeric delta_ = 0; }; constexpr TimeDelta TimeDelta::operator+(TimeDelta other) const { if (!other.is_inf()) return TimeDelta(delta_ + other.delta_); // Additions involving two infinities are only valid if signs match. CHECK(!is_inf() || (delta_ == other.delta_)); return other; } constexpr TimeDelta TimeDelta::operator-(TimeDelta other) const { if (!other.is_inf()) return TimeDelta(delta_ - other.delta_); // Subtractions involving two infinities are only valid if signs differ. CHECK_NE(int64_t{delta_}, int64_t{other.delta_}); return (other.delta_ < 0) ? Max() : Min(); } template constexpr TimeDelta operator*(T a, TimeDelta td) { return td * a; } // For logging use only. BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeDelta time_delta); // TimeBase-------------------------------------------------------------------- // Do not reference the time_internal::TimeBase template class directly. Please // use one of the time subclasses instead, and only reference the public // TimeBase members via those classes. namespace time_internal { // Provides value storage and comparison/math operations common to all time // classes. Each subclass provides for strong type-checking to ensure // semantically meaningful comparison/math of time values from the same clock // source or timeline. template class TimeBase { public: static constexpr int64_t kHoursPerDay = 24; static constexpr int64_t kSecondsPerMinute = 60; static constexpr int64_t kMinutesPerHour = 60; static constexpr int64_t kSecondsPerHour = kSecondsPerMinute * kMinutesPerHour; static constexpr int64_t kMillisecondsPerSecond = 1000; static constexpr int64_t kMillisecondsPerDay = kMillisecondsPerSecond * kSecondsPerHour * kHoursPerDay; static constexpr int64_t kMicrosecondsPerMillisecond = 1000; static constexpr int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * kMillisecondsPerSecond; static constexpr int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * kSecondsPerMinute; static constexpr int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * kMinutesPerHour; static constexpr int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * kHoursPerDay; static constexpr int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; static constexpr int64_t kNanosecondsPerMicrosecond = 1000; static constexpr int64_t kNanosecondsPerSecond = kNanosecondsPerMicrosecond * kMicrosecondsPerSecond; // TODO(https://crbug.com/1392437): Remove concept of "null" from base::Time. // // Warning: Be careful when writing code that performs math on time values, // since it's possible to produce a valid "zero" result that should not be // interpreted as a "null" value. If you find yourself using this method or // the zero-arg default constructor, please consider using an optional to // express the null state. // // Returns true if this object has not been initialized (probably). constexpr bool is_null() const { return us_ == 0; } // Returns true if this object represents the maximum/minimum time. constexpr bool is_max() const { return *this == Max(); } constexpr bool is_min() const { return *this == Min(); } constexpr bool is_inf() const { return is_min() || is_max(); } // Returns the maximum/minimum times, which should be greater/less than than // any reasonable time with which we might compare it. static constexpr TimeClass Max() { return TimeClass(std::numeric_limits::max()); } static constexpr TimeClass Min() { return TimeClass(std::numeric_limits::min()); } // For legacy serialization only. When serializing to `base::Value`, prefer // the helpers from //base/json/values_util.h instead. Otherwise, use // `Time::ToDeltaSinceWindowsEpoch()` for `Time` and // `TimeDelta::InMicroseconds()` for `TimeDelta`. See http://crbug.com/634507. constexpr int64_t ToInternalValue() const { return us_; } // The amount of time since the origin (or "zero") point. This is a syntactic // convenience to aid in code readability, mainly for debugging/testing use // cases. // // Warning: While the Time subclass has a fixed origin point, the origin for // the other subclasses can vary each time the application is restarted. constexpr TimeDelta since_origin() const; // Compute the difference between two times. #if !defined(__aarch64__) && BUILDFLAG(IS_ANDROID) NOINLINE // https://crbug.com/1369775 #endif constexpr TimeDelta operator-(const TimeBase& other) const; // Return a new time modified by some delta. constexpr TimeClass operator+(TimeDelta delta) const; constexpr TimeClass operator-(TimeDelta delta) const; // Modify by some time delta. constexpr TimeClass& operator+=(TimeDelta delta) { return static_cast(*this = (*this + delta)); } constexpr TimeClass& operator-=(TimeDelta delta) { return static_cast(*this = (*this - delta)); } // Comparison operators friend constexpr bool operator==(const TimeBase&, const TimeBase&) = default; friend constexpr std::strong_ordering operator<=>(const TimeBase&, const TimeBase&) = default; protected: constexpr explicit TimeBase(int64_t us) : us_(us) {} // Time value in a microsecond timebase. ClampedNumeric us_; }; #if BUILDFLAG(IS_WIN) #if defined(ARCH_CPU_ARM64) // TSCTicksPerSecond is not supported on Windows on Arm systems because the // cycle-counting methods use the actual CPU cycle count, and not a consistent // incrementing counter. #else // Returns true if the CPU support constant rate TSC. [[nodiscard]] BASE_EXPORT bool HasConstantRateTSC(); // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't // been measured yet. Needs to be guarded with a call to HasConstantRateTSC(). [[nodiscard]] BASE_EXPORT double TSCTicksPerSecond(); #endif #endif // BUILDFLAG(IS_WIN) } // namespace time_internal template inline constexpr TimeClass operator+(TimeDelta delta, TimeClass t) { return t + delta; } // Time ----------------------------------------------------------------------- // Represents a wall clock time in UTC. Values are not guaranteed to be // monotonically non-decreasing and are subject to large amounts of skew. // Time is stored internally as microseconds since the Windows epoch (1601). class BASE_EXPORT Time : public time_internal::TimeBase