Chromium Code Reviews| Index: src/base/platform/time.h |
| diff --git a/src/base/platform/time.h b/src/base/platform/time.h |
| index c8140efe4a50ba9a23802267adeba271400f20b0..6a3b73d33da8cb2e4304d79523c47e8e107a125f 100644 |
| --- a/src/base/platform/time.h |
| +++ b/src/base/platform/time.h |
| @@ -10,6 +10,7 @@ |
| #include <limits> |
| #include "src/base/macros.h" |
| +#include "src/base/safe_math.h" |
| // Forward declarations. |
| extern "C" { |
| @@ -23,8 +24,22 @@ namespace v8 { |
| namespace base { |
| class Time; |
| +class TimeDelta; |
| class TimeTicks; |
| +namespace time_internal { |
| + |
| +// Add or subtract |value| from a TimeDelta. The int64_t argument and return |
| +// value are in terms of a microsecond timebase. |
| +int64_t SaturatedAdd(TimeDelta delta, int64_t value); |
| +int64_t SaturatedSub(TimeDelta delta, int64_t value); |
| + |
| +// Clamp |value| on overflow and underflow conditions. The int64_t argument and |
| +// return value are in terms of a microsecond timebase. |
| +int64_t FromCheckedNumeric(const CheckedNumeric<int64_t> value); |
| + |
| +} // namespace time_internal |
| + |
| // ----------------------------------------------------------------------------- |
| // TimeDelta |
| // |
| @@ -143,6 +158,9 @@ class TimeDelta final { |
| } |
| 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. |
| @@ -153,35 +171,123 @@ class TimeDelta final { |
| }; |
| -// ----------------------------------------------------------------------------- |
| -// Time |
| -// |
| -// This class represents an absolute point in time, internally represented as |
| -// microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970. |
| +namespace time_internal { |
| + |
| +// TimeBase-------------------------------------------------------------------- |
| -class Time final { |
| +// 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_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 kMicrosecondsPerSecond = |
| + kMicrosecondsPerMillisecond * kMillisecondsPerSecond; |
| static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; |
| static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; |
| - static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * 24; |
| + 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; |
| - |
| - // Contains the NULL time. Use Time::Now() to get the current time. |
| - Time() : us_(0) {} |
| + static const int64_t kNanosecondsPerSecond = |
| + kNanosecondsPerMicrosecond * kMicrosecondsPerSecond; |
| - // Returns true if the time object has not been initialized. |
| - bool IsNull() const { return us_ == 0; } |
| + // 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 IsNull() const { |
| + return us_ == 0; |
| + } |
| - // Returns true if the time object is the maximum time. |
| + // Returns true if this object represents the maximum time. |
| bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); } |
|
fmeawad
2016/05/04 23:34:22
This method only exists in Time and not TimeTicks,
lpy
2016/05/05 00:00:04
Acknowledged.
|
| + // 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_t 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_t us) { return TimeClass(us); } |
| + |
| + protected: |
| + explicit TimeBase(int64_t us) : us_(us) {} |
| + |
| + // Time value in a microsecond timebase. |
| + int64_t us_; |
| +}; |
| + |
| +} // namespace time_internal |
| + |
| + |
| +// ----------------------------------------------------------------------------- |
| +// Time |
| +// |
| +// This class represents an absolute point in time, internally represented as |
| +// microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970. |
| + |
| +class Time : public time_internal::TimeBase<Time> { |
|
fmeawad
2016/05/04 23:34:22
Should this still be final?
lpy
2016/05/05 00:00:04
Done.
|
| + public: |
| + // Contains the NULL time. Use Time::Now() to get the current time. |
| + Time() : TimeBase(0) {} |
| + |
| // Returns the current time. Watch out, the system might adjust its clock |
| // in which case time will actually go backwards. We don't guarantee that |
| // times are increasing, or that two calls to Now() won't be the same. |
| @@ -200,15 +306,6 @@ class Time final { |
| // with which we might compare it. |
| static Time Max() { return Time(std::numeric_limits<int64_t>::max()); } |
| - // Converts to/from internal values. The meaning of the "internal value" is |
| - // completely up to the implementation, so it should be treated as opaque. |
| - static Time FromInternalValue(int64_t value) { |
| - return Time(value); |
| - } |
| - int64_t ToInternalValue() const { |
| - return us_; |
| - } |
| - |
| // Converts to/from POSIX time specs. |
| static Time FromTimespec(struct timespec ts); |
| struct timespec ToTimespec() const; |
| @@ -226,59 +323,9 @@ class Time final { |
| static Time FromJsTime(double ms_since_epoch); |
| double ToJsTime() const; |
| - Time& operator=(const Time& other) { |
| - us_ = other.us_; |
| - return *this; |
| - } |
| - |
| - // Compute the difference between two times. |
| - TimeDelta operator-(const Time& other) const { |
| - return TimeDelta::FromMicroseconds(us_ - other.us_); |
| - } |
| - |
| - // Modify by some time delta. |
| - Time& operator+=(const TimeDelta& delta) { |
| - us_ += delta.InMicroseconds(); |
| - return *this; |
| - } |
| - Time& operator-=(const TimeDelta& delta) { |
| - us_ -= delta.InMicroseconds(); |
| - return *this; |
| - } |
| - |
| - // Return a new time modified by some delta. |
| - Time operator+(const TimeDelta& delta) const { |
| - return Time(us_ + delta.InMicroseconds()); |
| - } |
| - Time operator-(const TimeDelta& delta) const { |
| - return Time(us_ - delta.InMicroseconds()); |
| - } |
| - |
| - // Comparison operators |
| - bool operator==(const Time& other) const { |
| - return us_ == other.us_; |
| - } |
| - bool operator!=(const Time& other) const { |
| - return us_ != other.us_; |
| - } |
| - bool operator<(const Time& other) const { |
| - return us_ < other.us_; |
| - } |
| - bool operator<=(const Time& other) const { |
| - return us_ <= other.us_; |
| - } |
| - bool operator>(const Time& other) const { |
| - return us_ > other.us_; |
| - } |
| - bool operator>=(const Time& other) const { |
| - return us_ >= other.us_; |
| - } |
| - |
| private: |
| - explicit Time(int64_t us) : us_(us) {} |
| - |
| - // Time in microseconds in UTC. |
| - int64_t us_; |
| + friend class time_internal::TimeBase<Time>; |
| + explicit Time(int64_t us) : TimeBase(us) {} |
| }; |
| std::ostream& operator<<(std::ostream&, const Time&); |
| @@ -298,9 +345,9 @@ inline Time operator+(const TimeDelta& delta, const Time& time) { |
| // Time::Now() may actually decrease or jump). But note that TimeTicks may |
| // "stand still", for example if the computer suspended. |
| -class TimeTicks final { |
| +class TimeTicks : public time_internal::TimeBase<TimeTicks> { |
|
fmeawad
2016/05/04 23:34:21
ditto
lpy
2016/05/05 00:00:04
Done.
|
| public: |
| - TimeTicks() : ticks_(0) {} |
| + TimeTicks() : TimeBase(0) {} |
| // Platform-dependent tick count representing "right now." |
| // The resolution of this clock is ~1-15ms. Resolution varies depending |
| @@ -318,73 +365,12 @@ class TimeTicks final { |
| // Returns true if the high-resolution clock is working on this system. |
| static bool IsHighResolutionClockWorking(); |
| - // Returns true if this object has not been initialized. |
| - bool IsNull() const { return ticks_ == 0; } |
| - |
| - // Converts to/from internal values. The meaning of the "internal value" is |
| - // completely up to the implementation, so it should be treated as opaque. |
| - static TimeTicks FromInternalValue(int64_t value) { |
| - return TimeTicks(value); |
| - } |
| - int64_t ToInternalValue() const { |
| - return ticks_; |
| - } |
| - |
| - TimeTicks& operator=(const TimeTicks other) { |
| - ticks_ = other.ticks_; |
| - return *this; |
| - } |
| - |
| - // Compute the difference between two times. |
| - TimeDelta operator-(const TimeTicks other) const { |
| - return TimeDelta::FromMicroseconds(ticks_ - other.ticks_); |
| - } |
| - |
| - // Modify by some time delta. |
| - TimeTicks& operator+=(const TimeDelta& delta) { |
| - ticks_ += delta.InMicroseconds(); |
| - return *this; |
| - } |
| - TimeTicks& operator-=(const TimeDelta& delta) { |
| - ticks_ -= delta.InMicroseconds(); |
| - return *this; |
| - } |
| - |
| - // Return a new TimeTicks modified by some delta. |
| - TimeTicks operator+(const TimeDelta& delta) const { |
| - return TimeTicks(ticks_ + delta.InMicroseconds()); |
| - } |
| - TimeTicks operator-(const TimeDelta& delta) const { |
| - return TimeTicks(ticks_ - delta.InMicroseconds()); |
| - } |
| - |
| - // Comparison operators |
| - bool operator==(const TimeTicks& other) const { |
| - return ticks_ == other.ticks_; |
| - } |
| - bool operator!=(const TimeTicks& other) const { |
| - return ticks_ != other.ticks_; |
| - } |
| - bool operator<(const TimeTicks& other) const { |
| - return ticks_ < other.ticks_; |
| - } |
| - bool operator<=(const TimeTicks& other) const { |
| - return ticks_ <= other.ticks_; |
| - } |
| - bool operator>(const TimeTicks& other) const { |
| - return ticks_ > other.ticks_; |
| - } |
| - bool operator>=(const TimeTicks& other) const { |
| - return ticks_ >= other.ticks_; |
| - } |
| - |
| private: |
| + friend class time_internal::TimeBase<TimeTicks>; |
| + |
| // Please use Now() to create a new object. This is for internal use |
| // and testing. Ticks is in microseconds. |
| - explicit TimeTicks(int64_t ticks) : ticks_(ticks) {} |
| - |
| - // Tick count in microseconds. |
| - int64_t ticks_; |
| + explicit TimeTicks(int64_t ticks) : TimeBase(ticks) {} |
| }; |
| inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) { |