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