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