Chromium Code Reviews| Index: base/time/time.h |
| diff --git a/base/time/time.h b/base/time/time.h |
| index 5c8b89c18cf174529c3220d1be399366ee15352e..0a2677838617e79ada4b219cc684631cf799a519 100644 |
| --- a/base/time/time.h |
| +++ b/base/time/time.h |
| @@ -57,8 +57,23 @@ |
| namespace base { |
| -class Time; |
| -class TimeTicks; |
| +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 argument and return value |
| +// are in terms of a microsecond timebase. |
| +BASE_EXPORT int64 SaturatedAdd(TimeDelta delta, int64 value); |
| +BASE_EXPORT int64 SaturatedSub(TimeDelta delta, int64 value); |
| + |
| +// Clamp |value| on overflow and underflow conditions. The int64 argument and |
| +// return value are in terms of a microsecond timebase. |
| +BASE_EXPORT int64 FromCheckedNumeric(const CheckedNumeric<int64> value); |
| + |
| +} // namespace time_internal |
| // TimeDelta ------------------------------------------------------------------ |
| @@ -110,6 +125,11 @@ class BASE_EXPORT TimeDelta { |
| 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 time delta. |
| bool is_max() const { |
| return delta_ == std::numeric_limits<int64>::max(); |
| @@ -141,19 +161,17 @@ class BASE_EXPORT TimeDelta { |
| // Computations with other deltas. |
| TimeDelta operator+(TimeDelta other) const { |
| - return TimeDelta(SaturatedAdd(other.delta_)); |
| + return TimeDelta(time_internal::SaturatedAdd(*this, other.delta_)); |
| } |
| TimeDelta operator-(TimeDelta other) const { |
| - return TimeDelta(SaturatedSub(other.delta_)); |
| + return TimeDelta(time_internal::SaturatedSub(*this, other.delta_)); |
| } |
| TimeDelta& operator+=(TimeDelta other) { |
| - delta_ = SaturatedAdd(other.delta_); |
| - return *this; |
| + return *this = (*this + other); |
| } |
| TimeDelta& operator-=(TimeDelta other) { |
| - delta_ = SaturatedSub(other.delta_); |
| - return *this; |
| + return *this = (*this - other); |
| } |
| TimeDelta operator-() const { |
| return TimeDelta(-delta_); |
| @@ -164,36 +182,29 @@ class BASE_EXPORT TimeDelta { |
| TimeDelta operator*(T a) const { |
| CheckedNumeric<int64> rv(delta_); |
| rv *= a; |
| - return TimeDelta(FromCheckedNumeric(rv)); |
| + return TimeDelta(time_internal::FromCheckedNumeric(rv)); |
| } |
| template<typename T> |
| TimeDelta operator/(T a) const { |
| CheckedNumeric<int64> rv(delta_); |
| rv /= a; |
| - return TimeDelta(FromCheckedNumeric(rv)); |
| + return TimeDelta(time_internal::FromCheckedNumeric(rv)); |
| } |
| template<typename T> |
| TimeDelta& operator*=(T a) { |
| - CheckedNumeric<int64> rv(delta_); |
| - rv *= a; |
| - delta_ = FromCheckedNumeric(rv); |
| - return *this; |
| + return *this = (*this * a); |
| } |
| template<typename T> |
| TimeDelta& operator/=(T a) { |
| - CheckedNumeric<int64> rv(delta_); |
| - rv /= a; |
| - delta_ = FromCheckedNumeric(rv); |
| - return *this; |
| + return *this = (*this / a); |
| } |
| int64 operator/(TimeDelta a) const { |
| return delta_ / a.delta_; |
| } |
| - |
| - // Defined below because it depends on the definition of the other classes. |
| - Time operator+(Time t) const; |
| - TimeTicks operator+(TimeTicks t) const; |
| + TimeDelta operator%(TimeDelta a) const { |
| + return TimeDelta(delta_ % a.delta_); |
| + } |
| // Comparison operators. |
| bool operator==(TimeDelta other) const { |
| @@ -216,8 +227,8 @@ class BASE_EXPORT TimeDelta { |
| } |
| private: |
| - friend class Time; |
| - friend class TimeTicks; |
| + friend int64 time_internal::SaturatedAdd(TimeDelta delta, int64 value); |
| + friend int64 time_internal::SaturatedSub(TimeDelta delta, int64 value); |
| // Constructs a delta given the duration in microseconds. This is private |
| // to avoid confusion by callers with an integer constructor. Use |
| @@ -225,13 +236,6 @@ class BASE_EXPORT TimeDelta { |
| explicit TimeDelta(int64 delta_us) : delta_(delta_us) { |
| } |
| - // Add or subtract |value| from this delta. |
| - int64 SaturatedAdd(int64 value) const; |
| - int64 SaturatedSub(int64 value) const; |
| - |
| - // Clamp |value| on overflow and underflow conditions. |
| - static int64 FromCheckedNumeric(const CheckedNumeric<int64> value); |
| - |
| // Delta in microseconds. |
| int64 delta_; |
| }; |
| @@ -244,10 +248,19 @@ inline TimeDelta operator*(T a, TimeDelta td) { |
| // For logging use only. |
| BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeDelta time_delta); |
| -// Time ----------------------------------------------------------------------- |
| +// 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-------------------------------------------------------------------- |
| -// Represents a wall clock time in UTC. |
| -class BASE_EXPORT Time { |
| +// 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 TimeClass> |
| +class TimeBase { |
| public: |
| static const int64 kHoursPerDay = 24; |
| static const int64 kMillisecondsPerSecond = 1000; |
| @@ -264,6 +277,102 @@ class BASE_EXPORT Time { |
| static const int64 kNanosecondsPerSecond = kNanosecondsPerMicrosecond * |
| kMicrosecondsPerSecond; |
| + // Returns true if this object has not been initialized. |
| + // |
| + // Warning: Be careful when writing code that performs math on time values, |
|
miu
2015/05/06 18:29:17
BTW--As I was looking through the code again, I re
|
| + // 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 time. |
| + bool is_max() const { |
| + return us_ == std::numeric_limits<int64>::max(); |
| + } |
| + |
| + // 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. |
| + int64 ToInternalValue() const { |
| + return us_; |
| + } |
| + |
| + TimeClass& operator=(TimeClass other) { |
| + us_ = other.us_; |
| + return *(static_cast<TimeClass*>(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<TimeClass&>(*this = (*this + delta)); |
| + } |
| + TimeClass& operator-=(TimeDelta delta) { |
| + return static_cast<TimeClass&>(*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. |
| + static TimeClass FromInternalValue(int64 us) { |
| + return TimeClass(us); |
| + } |
| + |
| + protected: |
| + explicit TimeBase(int64 us) : us_(us) { |
| + } |
| + |
| + // Time value in a microsecond timebase. |
| + int64 us_; |
| +}; |
| + |
| +} // namespace time_internal |
| + |
| +template<class TimeClass> |
| +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<Time> { |
| + public: |
| // The representation of Jan 1, 1970 UTC in microseconds since the |
| // platform-dependent epoch. |
| static const int64 kTimeTToMicrosecondsOffset; |
| @@ -303,17 +412,7 @@ class BASE_EXPORT Time { |
| }; |
| // Contains the NULL time. Use Time::Now() to get the current time. |
| - Time() : us_(0) { |
| - } |
| - |
| - // Returns true if the time object has not been initialized. |
| - bool is_null() const { |
| - return us_ == 0; |
| - } |
| - |
| - // Returns true if the time object is the maximum time. |
| - bool is_max() const { |
| - return us_ == std::numeric_limits<int64>::max(); |
| + Time() : TimeBase(0) { |
| } |
| // Returns the time for epoch in Unix-like system (Jan 1, 1970). |
| @@ -412,14 +511,6 @@ class BASE_EXPORT Time { |
| return FromExploded(true, exploded); |
| } |
| - // Converts an integer value representing Time to a class. This is used |
| - // when deserializing a |Time| 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. |
| - static Time FromInternalValue(int64 us) { |
| - return Time(us); |
| - } |
| - |
| // Converts a string representation of time to a Time object. |
| // An example of a time string which is converted is as below:- |
| // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified |
| @@ -435,13 +526,6 @@ class BASE_EXPORT Time { |
| return FromStringInternal(time_string, false, parsed_time); |
| } |
| - // For serializing, 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. |
| - int64 ToInternalValue() const { |
| - return us_; |
| - } |
| - |
| // Fills the given exploded structure with either the local time or UTC from |
| // this time structure (containing UTC). |
| void UTCExplode(Exploded* exploded) const { |
| @@ -455,58 +539,10 @@ class BASE_EXPORT Time { |
| // midnight on that day. |
| Time LocalMidnight() const; |
| - Time& operator=(Time other) { |
| - us_ = other.us_; |
| - return *this; |
| - } |
| - |
| - // Compute the difference between two times. |
| - TimeDelta operator-(Time other) const { |
| - return TimeDelta(us_ - other.us_); |
| - } |
| - |
| - // Modify by some time delta. |
| - Time& operator+=(TimeDelta delta) { |
| - us_ = delta.SaturatedAdd(us_); |
| - return *this; |
| - } |
| - Time& operator-=(TimeDelta delta) { |
| - us_ = -delta.SaturatedSub(us_); |
| - return *this; |
| - } |
| - |
| - // Return a new time modified by some delta. |
| - Time operator+(TimeDelta delta) const { |
| - return Time(delta.SaturatedAdd(us_)); |
| - } |
| - Time operator-(TimeDelta delta) const { |
| - return Time(-delta.SaturatedSub(us_)); |
| - } |
| - |
| - // Comparison operators |
| - bool operator==(Time other) const { |
| - return us_ == other.us_; |
| - } |
| - bool operator!=(Time other) const { |
| - return us_ != other.us_; |
| - } |
| - bool operator<(Time other) const { |
| - return us_ < other.us_; |
| - } |
| - bool operator<=(Time other) const { |
| - return us_ <= other.us_; |
| - } |
| - bool operator>(Time other) const { |
| - return us_ > other.us_; |
| - } |
| - bool operator>=(Time other) const { |
| - return us_ >= other.us_; |
| - } |
| - |
| private: |
| - friend class TimeDelta; |
| + friend class time_internal::TimeBase<Time>; |
| - explicit Time(int64 us) : us_(us) { |
| + explicit Time(int64 us) : TimeBase(us) { |
| } |
| // Explodes the given time to either local time |is_local = true| or UTC |
| @@ -527,9 +563,6 @@ class BASE_EXPORT Time { |
| static bool FromStringInternal(const char* time_string, |
| bool is_local, |
| Time* parsed_time); |
| - |
| - // Time in microseconds in UTC. |
| - int64 us_; |
| }; |
| // Inline the TimeDelta factory methods, for fast TimeDelta construction. |
| @@ -598,16 +631,13 @@ inline TimeDelta TimeDelta::FromMicroseconds(int64 us) { |
| return TimeDelta(us); |
| } |
| -inline Time TimeDelta::operator+(Time t) const { |
| - return Time(SaturatedAdd(t.us_)); |
| -} |
| - |
| // For logging use only. |
| BASE_EXPORT std::ostream& operator<<(std::ostream& os, Time time); |
| // TimeTicks ------------------------------------------------------------------ |
| -class BASE_EXPORT TimeTicks { |
| +// Represents monotonically non-decreasing clock time. |
| +class BASE_EXPORT TimeTicks : public time_internal::TimeBase<TimeTicks> { |
| public: |
| // We define this even without OS_CHROMEOS for seccomp sandbox testing. |
| #if defined(OS_LINUX) |
| @@ -617,7 +647,7 @@ class BASE_EXPORT TimeTicks { |
| static const clockid_t kClockSystemTrace = 11; |
| #endif |
| - TimeTicks() : ticks_(0) { |
| + TimeTicks() : TimeBase(0) { |
| } |
| // Platform-dependent tick count representing "right now." When |
| @@ -676,24 +706,6 @@ class BASE_EXPORT TimeTicks { |
| static TimeTicks FromQPCValue(LONGLONG qpc_value); |
| #endif |
| - // Returns true if this object has not been initialized. |
| - bool is_null() const { |
| - return ticks_ == 0; |
| - } |
| - |
| - // Returns true if the time delta is the maximum delta. |
| - bool is_max() const { |
| - return ticks_ == std::numeric_limits<int64>::max(); |
| - } |
| - |
| - // Converts an integer value representing TimeTicks to a class. This is used |
| - // when deserializing a |TimeTicks| 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. |
| - static TimeTicks FromInternalValue(int64 ticks) { |
| - return TimeTicks(ticks); |
| - } |
| - |
| // Get the TimeTick value at the time of the UnixEpoch. This is useful when |
| // you need to relate the value of TimeTicks to a real time and date. |
| // Note: Upon first invocation, this function takes a snapshot of the realtime |
| @@ -702,86 +714,26 @@ class BASE_EXPORT TimeTicks { |
| // application runs. |
| static TimeTicks UnixEpoch(); |
| - // Returns the internal numeric value of the TimeTicks object. |
| - // For serializing, use FromInternalValue to reconstitute. |
| - int64 ToInternalValue() const { |
| - return ticks_; |
| - } |
| - |
| // Returns |this| snapped to the next tick, given a |tick_phase| and |
| // repeating |tick_interval| in both directions. |this| may be before, |
| // after, or equal to the |tick_phase|. |
| TimeTicks SnappedToNextTick(TimeTicks tick_phase, |
| TimeDelta tick_interval) const; |
| - TimeTicks& operator=(TimeTicks other) { |
| - ticks_ = other.ticks_; |
| - return *this; |
| - } |
| - |
| - // Compute the difference between two times. |
| - TimeDelta operator-(TimeTicks other) const { |
| - return TimeDelta(ticks_ - other.ticks_); |
| - } |
| - |
| - // Modify by some time delta. |
| - TimeTicks& operator+=(TimeDelta delta) { |
| - ticks_ = delta.SaturatedAdd(ticks_); |
| - return *this; |
| - } |
| - TimeTicks& operator-=(TimeDelta delta) { |
| - ticks_ = -delta.SaturatedSub(ticks_); |
| - return *this; |
| - } |
| - |
| - // Return a new TimeTicks modified by some delta. |
| - TimeTicks operator+(TimeDelta delta) const { |
| - return TimeTicks(delta.SaturatedAdd(ticks_)); |
| - } |
| - TimeTicks operator-(TimeDelta delta) const { |
| - return TimeTicks(-delta.SaturatedSub(ticks_)); |
| - } |
| - |
| - // Comparison operators |
| - bool operator==(TimeTicks other) const { |
| - return ticks_ == other.ticks_; |
| - } |
| - bool operator!=(TimeTicks other) const { |
| - return ticks_ != other.ticks_; |
| - } |
| - bool operator<(TimeTicks other) const { |
| - return ticks_ < other.ticks_; |
| - } |
| - bool operator<=(TimeTicks other) const { |
| - return ticks_ <= other.ticks_; |
| - } |
| - bool operator>(TimeTicks other) const { |
| - return ticks_ > other.ticks_; |
| - } |
| - bool operator>=(TimeTicks other) const { |
| - return ticks_ >= other.ticks_; |
| - } |
| - |
| - protected: |
| - friend class TimeDelta; |
| - |
| - // Please use Now() to create a new object. This is for internal use |
| - // and testing. Ticks is in microseconds. |
| - explicit TimeTicks(int64 ticks) : ticks_(ticks) { |
| - } |
| - |
| - // Tick count in microseconds. |
| - int64 ticks_; |
| - |
| #if defined(OS_WIN) |
| + protected: |
| typedef DWORD (*TickFunctionType)(void); |
| static TickFunctionType SetMockTickFunction(TickFunctionType ticker); |
| #endif |
| -}; |
| -inline TimeTicks TimeDelta::operator+(TimeTicks t) const { |
| - return TimeTicks(SaturatedAdd(t.ticks_)); |
| -} |
| + private: |
| + friend class time_internal::TimeBase<TimeTicks>; |
| + |
| + // Please use Now() to create a new object. This is for internal use |
| + // and testing. |
| + explicit TimeTicks(int64 us) : TimeBase(us) { |
| + } |
| +}; |
| // For logging use only. |
| BASE_EXPORT std::ostream& operator<<(std::ostream& os, TimeTicks time_ticks); |