1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_BASE_PLATFORM_TIME_H_
6 #define V8_BASE_PLATFORM_TIME_H_
7
8 #include <stdint.h>
9
10 #include <ctime>
11 #include <iosfwd>
12 #include <limits>
13
14 #include "src/base/base-export.h"
15 #include "src/base/bits.h"
16 #include "src/base/macros.h"
17 #include "src/base/safe_math.h"
18 #if V8_OS_WIN
19 #include "src/base/win32-headers.h"
20 #endif
21
22 // Forward declarations.
23 extern "C" {
24 struct _FILETIME;
25 struct mach_timespec;
26 struct timespec;
27 struct timeval;
28 }
29
30 namespace v8 {
31 namespace base {
32
33 class Time;
34 class TimeDelta;
35 class TimeTicks;
36
37 namespace time_internal {
38 template<class TimeClass>
39 class TimeBase;
40 }
41
42 // -----------------------------------------------------------------------------
43 // TimeDelta
44 //
45 // This class represents a duration of time, internally represented in
46 // microseonds.
47
48 class V8_BASE_EXPORT TimeDelta final {
49 public:
TimeDelta()50 constexpr TimeDelta() : delta_(0) {}
51
52 // Converts units of time to TimeDeltas.
53 static TimeDelta FromDays(int days);
54 static TimeDelta FromHours(int hours);
55 static TimeDelta FromMinutes(int minutes);
56 static TimeDelta FromSeconds(int64_t seconds);
57 static TimeDelta FromMilliseconds(int64_t milliseconds);
FromMicroseconds(int64_t microseconds)58 static TimeDelta FromMicroseconds(int64_t microseconds) {
59 return TimeDelta(microseconds);
60 }
61 static TimeDelta FromNanoseconds(int64_t nanoseconds);
62
63 // Returns the maximum time delta, which should be greater than any reasonable
64 // time delta we might compare it to. Adding or subtracting the maximum time
65 // delta to a time or another time delta has an undefined result.
66 static constexpr TimeDelta Max();
67
68 // Returns the minimum time delta, which should be less than than any
69 // reasonable time delta we might compare it to. Adding or subtracting the
70 // minimum time delta to a time or another time delta has an undefined result.
71 static constexpr TimeDelta Min();
72
73 // Returns true if the time delta is zero.
IsZero()74 constexpr bool IsZero() const { return delta_ == 0; }
75
76 // Returns true if the time delta is the maximum/minimum time delta.
IsMax()77 constexpr bool IsMax() const {
78 return delta_ == std::numeric_limits<int64_t>::max();
79 }
IsMin()80 constexpr bool IsMin() const {
81 return delta_ == std::numeric_limits<int64_t>::min();
82 }
83
84 // Returns the time delta in some unit. The F versions return a floating
85 // point value, the "regular" versions return a rounded-down value.
86 //
87 // InMillisecondsRoundedUp() instead returns an integer that is rounded up
88 // to the next full millisecond.
89 int InDays() const;
90 int InHours() const;
91 int InMinutes() const;
92 double InSecondsF() const;
93 int64_t InSeconds() const;
94 double InMillisecondsF() const;
95 int64_t InMilliseconds() const;
96 int64_t InMillisecondsRoundedUp() const;
97 int64_t InMicroseconds() const;
98 int64_t InNanoseconds() const;
99
100 // Converts to/from Mach time specs.
101 static TimeDelta FromMachTimespec(struct mach_timespec ts);
102 struct mach_timespec ToMachTimespec() const;
103
104 // Converts to/from POSIX time specs.
105 static TimeDelta FromTimespec(struct timespec ts);
106 struct timespec ToTimespec() const;
107
108 TimeDelta& operator=(const TimeDelta& other) {
109 delta_ = other.delta_;
110 return *this;
111 }
112
113 // Computations with other deltas.
114 TimeDelta operator+(const TimeDelta& other) const {
115 return TimeDelta(delta_ + other.delta_);
116 }
117 TimeDelta operator-(const TimeDelta& other) const {
118 return TimeDelta(delta_ - other.delta_);
119 }
120
121 TimeDelta& operator+=(const TimeDelta& other) {
122 delta_ += other.delta_;
123 return *this;
124 }
125 TimeDelta& operator-=(const TimeDelta& other) {
126 delta_ -= other.delta_;
127 return *this;
128 }
129 constexpr TimeDelta operator-() const { return TimeDelta(-delta_); }
130
TimesOf(const TimeDelta & other)131 double TimesOf(const TimeDelta& other) const {
132 return static_cast<double>(delta_) / static_cast<double>(other.delta_);
133 }
PercentOf(const TimeDelta & other)134 double PercentOf(const TimeDelta& other) const {
135 return TimesOf(other) * 100.0;
136 }
137
138 // Computations with ints, note that we only allow multiplicative operations
139 // with ints, and additive operations with other deltas.
140 TimeDelta operator*(int64_t a) const {
141 return TimeDelta(delta_ * a);
142 }
143 TimeDelta operator/(int64_t a) const {
144 return TimeDelta(delta_ / a);
145 }
146 TimeDelta& operator*=(int64_t a) {
147 delta_ *= a;
148 return *this;
149 }
150 TimeDelta& operator/=(int64_t a) {
151 delta_ /= a;
152 return *this;
153 }
154 int64_t operator/(const TimeDelta& other) const {
155 return delta_ / other.delta_;
156 }
157
158 // Comparison operators.
159 constexpr bool operator==(const TimeDelta& other) const {
160 return delta_ == other.delta_;
161 }
162 constexpr bool operator!=(const TimeDelta& other) const {
163 return delta_ != other.delta_;
164 }
165 constexpr bool operator<(const TimeDelta& other) const {
166 return delta_ < other.delta_;
167 }
168 constexpr bool operator<=(const TimeDelta& other) const {
169 return delta_ <= other.delta_;
170 }
171 constexpr bool operator>(const TimeDelta& other) const {
172 return delta_ > other.delta_;
173 }
174 constexpr bool operator>=(const TimeDelta& other) const {
175 return delta_ >= other.delta_;
176 }
177
178 private:
179 template<class TimeClass> friend class time_internal::TimeBase;
180 // Constructs a delta given the duration in microseconds. This is private
181 // to avoid confusion by callers with an integer constructor. Use
182 // FromSeconds, FromMilliseconds, etc. instead.
TimeDelta(int64_t delta)183 explicit constexpr TimeDelta(int64_t delta) : delta_(delta) {}
184
185 // Delta in microseconds.
186 int64_t delta_;
187 };
188
189 // static
Max()190 constexpr TimeDelta TimeDelta::Max() {
191 return TimeDelta(std::numeric_limits<int64_t>::max());
192 }
193
194 // static
Min()195 constexpr TimeDelta TimeDelta::Min() {
196 return TimeDelta(std::numeric_limits<int64_t>::min());
197 }
198
199 namespace time_internal {
200
201 // TimeBase--------------------------------------------------------------------
202
203 // Provides value storage and comparison/math operations common to all time
204 // classes. Each subclass provides for strong type-checking to ensure
205 // semantically meaningful comparison/math of time values from the same clock
206 // source or timeline.
207 template<class TimeClass>
208 class TimeBase {
209 public:
210 static constexpr int64_t kHoursPerDay = 24;
211 static constexpr int64_t kMillisecondsPerSecond = 1000;
212 static constexpr int64_t kMillisecondsPerDay =
213 kMillisecondsPerSecond * 60 * 60 * kHoursPerDay;
214 static constexpr int64_t kMicrosecondsPerMillisecond = 1000;
215 static constexpr int64_t kMicrosecondsPerSecond =
216 kMicrosecondsPerMillisecond * kMillisecondsPerSecond;
217 static constexpr int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
218 static constexpr int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
219 static constexpr int64_t kMicrosecondsPerDay =
220 kMicrosecondsPerHour * kHoursPerDay;
221 static constexpr int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
222 static constexpr int64_t kNanosecondsPerMicrosecond = 1000;
223 static constexpr int64_t kNanosecondsPerSecond =
224 kNanosecondsPerMicrosecond * kMicrosecondsPerSecond;
225
226 #if V8_OS_WIN
227 // To avoid overflow in QPC to Microseconds calculations, since we multiply
228 // by kMicrosecondsPerSecond, then the QPC value should not exceed
229 // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply.
230 static constexpr int64_t kQPCOverflowThreshold = INT64_C(0x8637BD05AF7);
231 #endif
232
233 // Returns true if this object has not been initialized.
234 //
235 // Warning: Be careful when writing code that performs math on time values,
236 // since it's possible to produce a valid "zero" result that should not be
237 // interpreted as a "null" value.
IsNull()238 constexpr bool IsNull() const { return us_ == 0; }
239
240 // Returns the maximum/minimum times, which should be greater/less than any
241 // reasonable time with which we might compare it.
Max()242 static TimeClass Max() {
243 return TimeClass(std::numeric_limits<int64_t>::max());
244 }
Min()245 static TimeClass Min() {
246 return TimeClass(std::numeric_limits<int64_t>::min());
247 }
248
249 // Returns true if this object represents the maximum/minimum time.
IsMax()250 constexpr bool IsMax() const {
251 return us_ == std::numeric_limits<int64_t>::max();
252 }
IsMin()253 constexpr bool IsMin() const {
254 return us_ == std::numeric_limits<int64_t>::min();
255 }
256
257 // For serializing only. Use FromInternalValue() to reconstitute. Please don't
258 // use this and do arithmetic on it, as it is more error prone than using the
259 // provided operators.
ToInternalValue()260 int64_t ToInternalValue() const { return us_; }
261
262 TimeClass& operator=(TimeClass other) {
263 us_ = other.us_;
264 return *(static_cast<TimeClass*>(this));
265 }
266
267 // Compute the difference between two times.
268 TimeDelta operator-(TimeClass other) const {
269 return TimeDelta::FromMicroseconds(us_ - other.us_);
270 }
271
272 // Return a new time modified by some delta.
273 TimeClass operator+(TimeDelta delta) const {
274 return TimeClass(bits::SignedSaturatedAdd64(delta.delta_, us_));
275 }
276 TimeClass operator-(TimeDelta delta) const {
277 return TimeClass(-bits::SignedSaturatedSub64(delta.delta_, us_));
278 }
279
280 // Modify by some time delta.
281 TimeClass& operator+=(TimeDelta delta) {
282 return static_cast<TimeClass&>(*this = (*this + delta));
283 }
284 TimeClass& operator-=(TimeDelta delta) {
285 return static_cast<TimeClass&>(*this = (*this - delta));
286 }
287
288 // Comparison operators
289 bool operator==(TimeClass other) const {
290 return us_ == other.us_;
291 }
292 bool operator!=(TimeClass other) const {
293 return us_ != other.us_;
294 }
295 bool operator<(TimeClass other) const {
296 return us_ < other.us_;
297 }
298 bool operator<=(TimeClass other) const {
299 return us_ <= other.us_;
300 }
301 bool operator>(TimeClass other) const {
302 return us_ > other.us_;
303 }
304 bool operator>=(TimeClass other) const {
305 return us_ >= other.us_;
306 }
307
308 // Converts an integer value representing TimeClass to a class. This is used
309 // when deserializing a |TimeClass| structure, using a value known to be
310 // compatible. It is not provided as a constructor because the integer type
311 // may be unclear from the perspective of a caller.
FromInternalValue(int64_t us)312 static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); }
313
314 protected:
TimeBase(int64_t us)315 explicit constexpr TimeBase(int64_t us) : us_(us) {}
316
317 // Time value in a microsecond timebase.
318 int64_t us_;
319 };
320
321 } // namespace time_internal
322
323
324 // -----------------------------------------------------------------------------
325 // Time
326 //
327 // This class represents an absolute point in time, internally represented as
328 // microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970.
329
330 class V8_BASE_EXPORT Time final : public time_internal::TimeBase<Time> {
331 public:
332 // Contains the nullptr time. Use Time::Now() to get the current time.
Time()333 constexpr Time() : TimeBase(0) {}
334
335 // Returns the current time. Watch out, the system might adjust its clock
336 // in which case time will actually go backwards. We don't guarantee that
337 // times are increasing, or that two calls to Now() won't be the same.
338 static Time Now();
339
340 // Returns the current time. Same as Now() except that this function always
341 // uses system time so that there are no discrepancies between the returned
342 // time and system time even on virtual environments including our test bot.
343 // For timing sensitive unittests, this function should be used.
344 static Time NowFromSystemTime();
345
346 // Returns the time for epoch in Unix-like system (Jan 1, 1970).
UnixEpoch()347 static Time UnixEpoch() { return Time(0); }
348
349 // Converts to/from POSIX time specs.
350 static Time FromTimespec(struct timespec ts);
351 struct timespec ToTimespec() const;
352
353 // Converts to/from POSIX time values.
354 static Time FromTimeval(struct timeval tv);
355 struct timeval ToTimeval() const;
356
357 // Converts to/from Windows file times.
358 static Time FromFiletime(struct _FILETIME ft);
359 struct _FILETIME ToFiletime() const;
360
361 // Converts to/from the Javascript convention for times, a number of
362 // milliseconds since the epoch:
363 static Time FromJsTime(double ms_since_epoch);
364 double ToJsTime() const;
365
366 private:
367 friend class time_internal::TimeBase<Time>;
Time(int64_t us)368 explicit constexpr Time(int64_t us) : TimeBase(us) {}
369 };
370
371 V8_BASE_EXPORT std::ostream& operator<<(std::ostream&, const Time&);
372
373 inline Time operator+(const TimeDelta& delta, const Time& time) {
374 return time + delta;
375 }
376
377
378 // -----------------------------------------------------------------------------
379 // TimeTicks
380 //
381 // This class represents an abstract time that is most of the time incrementing
382 // for use in measuring time durations. It is internally represented in
383 // microseconds. It can not be converted to a human-readable time, but is
384 // guaranteed not to decrease (if the user changes the computer clock,
385 // Time::Now() may actually decrease or jump). But note that TimeTicks may
386 // "stand still", for example if the computer suspended.
387
388 class V8_BASE_EXPORT TimeTicks final
389 : public time_internal::TimeBase<TimeTicks> {
390 public:
TimeTicks()391 constexpr TimeTicks() : TimeBase(0) {}
392
393 // Platform-dependent tick count representing "right now." When
394 // IsHighResolution() returns false, the resolution of the clock could be as
395 // coarse as ~15.6ms. Otherwise, the resolution should be no worse than one
396 // microsecond.
397 // This method never returns a null TimeTicks.
398 static TimeTicks Now();
399
400 // This is equivalent to Now() but DCHECKs that IsHighResolution(). Useful for
401 // test frameworks that rely on high resolution clocks (in practice all
402 // platforms but low-end Windows devices have high resolution clocks).
403 static TimeTicks HighResolutionNow();
404
405 // Returns true if the high-resolution clock is working on this system.
406 static bool IsHighResolution();
407
408 private:
409 friend class time_internal::TimeBase<TimeTicks>;
410
411 // Please use Now() to create a new object. This is for internal use
412 // and testing. Ticks are in microseconds.
TimeTicks(int64_t ticks)413 explicit constexpr TimeTicks(int64_t ticks) : TimeBase(ticks) {}
414 };
415
416 inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) {
417 return ticks + delta;
418 }
419
420
421 // ThreadTicks ----------------------------------------------------------------
422
423 // Represents a clock, specific to a particular thread, than runs only while the
424 // thread is running.
425 class V8_BASE_EXPORT ThreadTicks final
426 : public time_internal::TimeBase<ThreadTicks> {
427 public:
ThreadTicks()428 constexpr ThreadTicks() : TimeBase(0) {}
429
430 // Returns true if ThreadTicks::Now() is supported on this system.
431 static bool IsSupported();
432
433 // Waits until the initialization is completed. Needs to be guarded with a
434 // call to IsSupported().
WaitUntilInitialized()435 static void WaitUntilInitialized() {
436 #if V8_OS_WIN
437 WaitUntilInitializedWin();
438 #endif
439 }
440
441 // Returns thread-specific CPU-time on systems that support this feature.
442 // Needs to be guarded with a call to IsSupported(). Use this timer
443 // to (approximately) measure how much time the calling thread spent doing
444 // actual work vs. being de-scheduled. May return bogus results if the thread
445 // migrates to another CPU between two calls. Returns an empty ThreadTicks
446 // object until the initialization is completed. If a clock reading is
447 // absolutely needed, call WaitUntilInitialized() before this method.
448 static ThreadTicks Now();
449
450 #if V8_OS_WIN
451 // Similar to Now() above except this returns thread-specific CPU time for an
452 // arbitrary thread. All comments for Now() method above apply apply to this
453 // method as well.
454 static ThreadTicks GetForThread(const HANDLE& thread_handle);
455 #endif
456
457 private:
458 template <class TimeClass>
459 friend class time_internal::TimeBase;
460
461 // Please use Now() or GetForThread() to create a new object. This is for
462 // internal use and testing. Ticks are in microseconds.
ThreadTicks(int64_t ticks)463 explicit constexpr ThreadTicks(int64_t ticks) : TimeBase(ticks) {}
464
465 #if V8_OS_WIN
466 // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't
467 // been measured yet. Needs to be guarded with a call to IsSupported().
468 static double TSCTicksPerSecond();
469 static bool IsSupportedWin();
470 static void WaitUntilInitializedWin();
471 #endif
472 };
473
474 } // namespace base
475 } // namespace v8
476
477 #endif // V8_BASE_PLATFORM_TIME_H_
478