// 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 can not 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_POSIX) #include #include #endif #if defined(OS_WIN) // For FILETIME in FromFileTime, until it moves to a new converter class. // See TODO(iyengar) below. #include #include "base/gtest_prod_util.h" #endif 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 |value| from a TimeDelta. The int64_t argument and return // value are in terms of a microsecond timebase. BASE_EXPORT int64_t SaturatedAdd(TimeDelta delta, int64_t value); BASE_EXPORT int64_t SaturatedSub(TimeDelta delta, int64_t value); } // namespace time_internal // TimeDelta ------------------------------------------------------------------ class BASE_EXPORT TimeDelta { public: constexpr TimeDelta() : delta_(0) {} // Converts units of time to TimeDeltas. 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 FromSecondsD(double secs); static constexpr TimeDelta FromMillisecondsD(double ms); static constexpr TimeDelta FromMicroseconds(int64_t us); #if defined(OS_POSIX) static TimeDelta FromTimeSpec(const timespec& ts); #endif #if defined(OS_WIN) static TimeDelta FromQPCValue(LONGLONG qpc_value); #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 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 int64_t ToInternalValue() const { return delta_; } // Returns the magnitude (absolute value) of this TimeDelta. 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. bool is_zero() const { return delta_ == 0; } // Returns true if the time delta is the maximum/minimum time delta. bool is_max() const { return delta_ == std::numeric_limits::max(); } bool is_min() const { return delta_ == std::numeric_limits::min(); } #if defined(OS_POSIX) struct timespec ToTimeSpec() const; #endif // Returns the time delta in some unit. The F versions return a floating // point value, the "regular" versions return a rounded-down value. // // InMillisecondsRoundedUp() instead returns an integer that is rounded up // to the next full millisecond. int InDays() 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; int64_t InMicroseconds() const; int64_t InNanoseconds() const; TimeDelta& operator=(TimeDelta other) { delta_ = other.delta_; return *this; } // Computations with other deltas. TimeDelta operator+(TimeDelta other) const { return TimeDelta(time_internal::SaturatedAdd(*this, other.delta_)); } TimeDelta operator-(TimeDelta other) const { return TimeDelta(time_internal::SaturatedSub(*this, other.delta_)); } TimeDelta& operator+=(TimeDelta other) { return *this = (*this + other); } TimeDelta& operator-=(TimeDelta other) { return *this = (*this - other); } TimeDelta operator-() const { return TimeDelta(-delta_); } // Computations with numeric types. template 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 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 TimeDelta& operator*=(T a) { return *this = (*this * a); } template TimeDelta& operator/=(T a) { return *this = (*this / a); } int64_t operator/(TimeDelta a) const { return delta_ / a.delta_; } TimeDelta operator%(TimeDelta a) const { return TimeDelta(delta_ % a.delta_); } // 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_; } #if defined(OS_WIN) // This works around crbug.com/635974 constexpr TimeDelta(const TimeDelta& other) : delta_(other.delta_) {} #endif private: friend int64_t time_internal::SaturatedAdd(TimeDelta delta, int64_t value); friend int64_t time_internal::SaturatedSub(TimeDelta delta, int64_t value); // 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 inline 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 { // 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 const int64_t kHoursPerDay = 24; static const int64_t kMillisecondsPerSecond = 1000; static const int64_t kMillisecondsPerDay = kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; static const int64_t kMicrosecondsPerMillisecond = 1000; static const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * kMillisecondsPerSecond; static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * kHoursPerDay; static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; static const int64_t kNanosecondsPerMicrosecond = 1000; static const 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. bool is_null() const { return us_ == 0; } // Returns true if this object represents the maximum/minimum time. bool is_max() const { return us_ == std::numeric_limits::max(); } 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 TimeClass Max() { return TimeClass(std::numeric_limits::max()); } static 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. http://crbug.com/634507 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. TimeDelta since_origin() const { return TimeDelta::FromMicroseconds(us_); } TimeClass& operator=(TimeClass other) { us_ = other.us_; return *(static_cast(this)); } // Compute the difference between two times. TimeDelta operator-(TimeClass other) const { return TimeDelta::FromMicroseconds(us_ - other.us_); } // Return a new time modified by some delta. TimeClass operator+(TimeDelta delta) const { return TimeClass(time_internal::SaturatedAdd(delta, us_)); } TimeClass operator-(TimeDelta delta) const { return TimeClass(-time_internal::SaturatedSub(delta, us_)); } // Modify by some time delta. TimeClass& operator+=(TimeDelta delta) { return static_cast(*this = (*this + delta)); } TimeClass& operator-=(TimeDelta delta) { return static_cast(*this = (*this - delta)); } // Comparison operators bool operator==(TimeClass other) const { return us_ == other.us_; } bool operator!=(TimeClass other) const { return us_ != other.us_; } bool operator<(TimeClass other) const { return us_ < other.us_; } bool operator<=(TimeClass other) const { return us_ <= other.us_; } bool operator>(TimeClass other) const { return us_ > other.us_; } bool operator>=(TimeClass other) const { return us_ >= other.us_; } // Converts an integer value representing TimeClass to a class. This is used // when deserializing a |TimeClass| 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 TimeClass FromInternalValue(int64_t us) { return TimeClass(us); } protected: constexpr explicit TimeBase(int64_t us) : us_(us) {} // Time value in a microsecond timebase. int64_t us_; }; } // namespace time_internal template inline 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. class BASE_EXPORT Time : public time_internal::TimeBase