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 | 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 | 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 | 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 | return delta_ == std::numeric_limits<int64_t>::max(); |
109 | } |
110 | constexpr bool IsMin() const { |
111 | 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 | return TimeDelta(delta_ + other.delta_); |
141 | } |
142 | TimeDelta operator-(const TimeDelta& other) const { |
143 | return TimeDelta(delta_ - other.delta_); |
144 | } |
145 | |
146 | TimeDelta& operator+=(const TimeDelta& other) { |
147 | delta_ += other.delta_; |
148 | return *this; |
149 | } |
150 | TimeDelta& operator-=(const TimeDelta& other) { |
151 | delta_ -= other.delta_; |
152 | return *this; |
153 | } |
154 | constexpr TimeDelta operator-() const { return TimeDelta(-delta_); } |
155 | |
156 | double TimesOf(const TimeDelta& other) const { |
157 | return static_cast<double>(delta_) / static_cast<double>(other.delta_); |
158 | } |
159 | double PercentOf(const TimeDelta& other) const { |
160 | 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 | delta_ *= a; |
173 | return *this; |
174 | } |
175 | TimeDelta& operator/=(int64_t a) { |
176 | 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 | return delta_ == other.delta_; |
186 | } |
187 | constexpr bool operator!=(const TimeDelta& other) const { |
188 | return delta_ != other.delta_; |
189 | } |
190 | constexpr bool operator<(const TimeDelta& other) const { |
191 | return delta_ < other.delta_; |
192 | } |
193 | constexpr bool operator<=(const TimeDelta& other) const { |
194 | return delta_ <= other.delta_; |
195 | } |
196 | constexpr bool operator>(const TimeDelta& other) const { |
197 | 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 | 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 | 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 | 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 | return TimeDelta::FromMicroseconds(us_ - other.us_); |
279 | } |
280 | |
281 | // Return a new time modified by some delta. |
282 | TimeClass operator+(TimeDelta delta) const { |
283 | return TimeClass(bits::SignedSaturatedAdd64(delta.delta_, us_)); |
284 | } |
285 | TimeClass operator-(TimeDelta delta) const { |
286 | 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 | 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 | bool operator<=(TimeClass other) const { |
308 | return us_ <= other.us_; |
309 | } |
310 | bool operator>(TimeClass other) const { |
311 | return us_ > other.us_; |
312 | } |
313 | bool operator>=(TimeClass other) const { |
314 | 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 | 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_ |
487 | |