Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Unified Diff: src/base/platform/time.h

Issue 1952843002: Create TimeBase for time related classes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/base/platform/time.cc » ('j') | src/base/platform/time.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « no previous file | src/base/platform/time.cc » ('j') | src/base/platform/time.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698