// Copyright (c) 2012 The Chromium Authors. All rights reserved. // 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. // As a result, prefer passing them by value: // void MyFunction(TimeDelta arg); // If circumstances require, you may also pass by const reference: // void MyFunction(const TimeDelta& arg); // Not preferred. // // Definitions of operator<< are provided to make these types work with // DCHECK_EQ() and other log macros. For human-readable formatting, see // "base/i18n/time_formatting.h". // // So many choices! Which time class should you use? Examples: // // 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. #ifndef BASE_TIME_TIME_H_ #define BASE_TIME_TIME_H_ #include #include #include #include #include "base/base_export.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/numerics/safe_math.h" #include "build/build_config.h" #if defined(OS_FUCHSIA) #include #endif #if defined(OS_MACOSX) #include // Avoid Mac system header macro leak. #undef TYPE_BOOL #endif #if defined(OS_ANDROID) #include #endif #if defined(OS_POSIX) || defined(OS_FUCHSIA) #include #include #endif #if defined(OS_WIN) #include "base/gtest_prod_util.h" #include "base/win/windows_types.h" #endif namespace ABI { namespace Windows { namespace Foundation { struct DateTime; } // namespace Foundation } // namespace Windows } // namespace ABI namespace base { class PlatformThreadHandle; class TimeDelta; // The functions in the time_internal namespace are meant to be used only by the // time classes and functions. Please use the math operators defined in the // time classes instead. namespace time_internal { // Add or subtract a TimeDelta from |value|. TimeDelta::Min()/Max() are treated // as infinity and will always saturate the return value (infinity math applies // if |value| also is at either limit of its spectrum). The int64_t argument and // return value are in terms of a microsecond timebase. BASE_EXPORT constexpr int64_t SaturatedAdd(int64_t value, TimeDelta delta); BASE_EXPORT constexpr int64_t SaturatedSub(int64_t value, TimeDelta delta); } // namespace time_internal // TimeDelta ------------------------------------------------------------------ class BASE_EXPORT TimeDelta { public: constexpr TimeDelta() : delta_(0) {} // Converts units of time to TimeDeltas. // WARNING: Floating point arithmetic is such that FromXXXD(t.InXXXF()) may // not precisely equal |t|. Hence, floating point values should not be used // for storage. static constexpr TimeDelta FromDays(int days); static constexpr TimeDelta FromHours(int hours); static constexpr TimeDelta FromMinutes(int minutes); static constexpr TimeDelta FromSeconds(int64_t secs); static constexpr TimeDelta FromMilliseconds(int64_t ms); static constexpr TimeDelta FromMicroseconds(int64_t us); static constexpr TimeDelta FromNanoseconds(int64_t ns); static constexpr TimeDelta FromSecondsD(double secs); static constexpr TimeDelta FromMillisecondsD(double ms); static constexpr TimeDelta FromMicrosecondsD(double us); static constexpr TimeDelta FromNanosecondsD(double ns); #if defined(OS_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); #elif defined(OS_POSIX) || defined(OS_FUCHSIA) static TimeDelta FromTimeSpec(const timespec& ts); #endif #if defined(OS_FUCHSIA) static TimeDelta FromZxDuration(zx_duration_t nanos); #endif // 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. Adding or subtracting the maximum time // delta to a time or another time delta has an undefined result. static constexpr TimeDelta Max(); // Returns the minimum time delta, which should be less than than any // reasonable time delta we might compare it to. Adding or subtracting the // minimum time delta to a time or another time delta has an undefined result. static constexpr TimeDelta Min(); // 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 { // Some toolchains provide an incomplete C++11 implementation and lack an // int64_t overload for std::abs(). The following is a simple branchless // implementation: const int64_t mask = delta_ >> (sizeof(delta_) * 8 - 1); return TimeDelta((delta_ + mask) ^ mask); } // Returns true if the time delta is zero. constexpr bool is_zero() const { return delta_ == 0; } // Returns true if the time delta is the maximum/minimum time delta. constexpr bool is_max() const { return delta_ == std::numeric_limits::max(); } constexpr bool is_min() const { return delta_ == std::numeric_limits::min(); } #if defined(OS_POSIX) || defined(OS_FUCHSIA) struct timespec ToTimeSpec() const; #endif #if defined(OS_FUCHSIA) zx_duration_t ToZxDuration() const; #endif #if defined(OS_WIN) ABI::Windows::Foundation::DateTime ToWinrtDateTime() const; #endif // Returns the time delta in some unit. 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 FromXXXD(t.InXXXF()) may // not precisely equal |t|. Hence, floating point values should not be used // for storage. int InDays() const; int InDaysFloored() const; int InHours() const; int InMinutes() const; double InSecondsF() const; int64_t InSeconds() const; double InMillisecondsF() const; int64_t InMilliseconds() const; int64_t InMillisecondsRoundedUp() const; constexpr int64_t InMicroseconds() const { return delta_; } double InMicrosecondsF() const; int64_t InNanoseconds() const; // Computations with other deltas. constexpr TimeDelta operator+(TimeDelta other) const { return TimeDelta(time_internal::SaturatedAdd(delta_, other)); } constexpr TimeDelta operator-(TimeDelta other) const { return TimeDelta(time_internal::SaturatedSub(delta_, other)); } constexpr TimeDelta& operator+=(TimeDelta other) { return *this = (*this + other); } constexpr TimeDelta& operator-=(TimeDelta other) { return *this = (*this - other); } constexpr TimeDelta operator-() const { return TimeDelta(-delta_); } // Computations with numeric types. template constexpr TimeDelta operator*(T a) const { CheckedNumeric rv(delta_); rv *= a; if (rv.IsValid()) return TimeDelta(rv.ValueOrDie()); // Matched sign overflows. Mismatched sign underflows. if ((delta_ < 0) ^ (a < 0)) return TimeDelta(std::numeric_limits::min()); return TimeDelta(std::numeric_limits::max()); } template constexpr TimeDelta operator/(T a) const { CheckedNumeric rv(delta_); rv /= a; if (rv.IsValid()) return TimeDelta(rv.ValueOrDie()); // Matched sign overflows. Mismatched sign underflows. // Special case to catch divide by zero. if ((delta_ < 0) ^ (a <= 0)) return TimeDelta(std::numeric_limits::min()); return TimeDelta(std::numeric_limits::max()); } template constexpr TimeDelta& operator*=(T a) { return *this = (*this * a); } template constexpr TimeDelta& operator/=(T a) { return *this = (*this / a); } constexpr int64_t operator/(TimeDelta a) const { return delta_ / a.delta_; } constexpr TimeDelta operator%(TimeDelta a) const { return TimeDelta(delta_ % a.delta_); } TimeDelta& operator%=(TimeDelta other) { return *this = (*this % other); } // Comparison operators. constexpr bool operator==(TimeDelta other) const { return delta_ == other.delta_; } constexpr bool operator!=(TimeDelta other) const { return delta_ != other.delta_; } constexpr bool operator<(TimeDelta other) const { return delta_ < other.delta_; } constexpr bool operator<=(TimeDelta other) const { return delta_ <= other.delta_; } constexpr bool operator>(TimeDelta other) const { return delta_ > other.delta_; } constexpr bool operator>=(TimeDelta other) const { return delta_ >= other.delta_; } private: friend constexpr int64_t time_internal::SaturatedAdd(int64_t value, TimeDelta delta); friend constexpr int64_t time_internal::SaturatedSub(int64_t value, TimeDelta delta); // Constructs a delta given the duration in microseconds. This is private // to avoid confusion by callers with an integer constructor. Use // FromSeconds, FromMilliseconds, etc. instead. constexpr explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {} // Private method to build a delta from a double. static constexpr TimeDelta FromDouble(double value); // Private method to build a delta from the product of a user-provided value // and a known-positive value. static constexpr TimeDelta FromProduct(int64_t value, int64_t positive_value); // Delta in microseconds. int64_t delta_; }; 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); // 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 { constexpr int64_t SaturatedAdd(int64_t value, TimeDelta delta) { // Treat Min/Max() as +/- infinity (additions involving two infinities are // only valid if signs match). if (delta.is_max()) { CHECK_GT(value, std::numeric_limits::min()); return std::numeric_limits::max(); } else if (delta.is_min()) { CHECK_LT(value, std::numeric_limits::max()); return std::numeric_limits::min(); } return base::ClampAdd(value, delta.delta_); } constexpr int64_t SaturatedSub(int64_t value, TimeDelta delta) { // Treat Min/Max() as +/- infinity (subtractions involving two infinities are // only valid if signs are opposite). if (delta.is_max()) { CHECK_LT(value, std::numeric_limits::max()); return std::numeric_limits::min(); } else if (delta.is_min()) { CHECK_GT(value, std::numeric_limits::min()); return std::numeric_limits::max(); } return base::ClampSub(value, delta.delta_); } // TimeBase-------------------------------------------------------------------- // 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 kSecondsPerHour = 60 * kSecondsPerMinute; static constexpr int64_t kMillisecondsPerSecond = 1000; static constexpr int64_t kMillisecondsPerDay = kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; static constexpr int64_t kMicrosecondsPerMillisecond = 1000; static constexpr int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * kMillisecondsPerSecond; static constexpr int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; static constexpr int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; 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; // Returns true if this object has not been initialized. // // 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. constexpr bool is_null() const { return us_ == 0; } // Returns true if this object represents the maximum/minimum time. constexpr bool is_max() const { return us_ == std::numeric_limits::max(); } constexpr bool is_min() const { return us_ == std::numeric_limits::min(); } // 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 serializing only. Use FromInternalValue() to reconstitute. Please don't // use this and do arithmetic on it, as it is more error prone than using the // provided operators. // // DEPRECATED - Do not use in new code. For serializing Time values, prefer // Time::ToDeltaSinceWindowsEpoch().InMicroseconds(). 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 { return TimeDelta::FromMicroseconds(us_); } constexpr TimeClass& operator=(TimeClass other) { us_ = other.us_; return *(static_cast(this)); } // Compute the difference between two times. constexpr TimeDelta operator-(TimeClass other) const { return TimeDelta::FromMicroseconds(us_ - other.us_); } // Return a new time modified by some delta. constexpr TimeClass operator+(TimeDelta delta) const { return TimeClass(time_internal::SaturatedAdd(us_, delta)); } constexpr TimeClass operator-(TimeDelta delta) const { return TimeClass(time_internal::SaturatedSub(us_, delta)); } // 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 constexpr bool operator==(TimeClass other) const { return us_ == other.us_; } constexpr bool operator!=(TimeClass other) const { return us_ != other.us_; } constexpr bool operator<(TimeClass other) const { return us_ < other.us_; } constexpr bool operator<=(TimeClass other) const { return us_ <= other.us_; } constexpr bool operator>(TimeClass other) const { return us_ > other.us_; } constexpr bool operator>=(TimeClass other) const { return us_ >= other.us_; } protected: constexpr explicit TimeBase(int64_t us) : us_(us) {} // Time value in a microsecond timebase. int64_t us_; }; } // 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