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/macros.h" 13 14 // Forward declarations. 15 extern "C" { 16 struct _FILETIME; 17 struct mach_timespec; 18 struct timespec; 19 struct timeval; 20 } 21 22 namespace v8 { 23 namespace base { 24 25 class Time; 26 class TimeTicks; 27 28 // ----------------------------------------------------------------------------- 29 // TimeDelta 30 // 31 // This class represents a duration of time, internally represented in 32 // microseonds. 33 34 class TimeDelta final { 35 public: TimeDelta()36 TimeDelta() : delta_(0) {} 37 38 // Converts units of time to TimeDeltas. 39 static TimeDelta FromDays(int days); 40 static TimeDelta FromHours(int hours); 41 static TimeDelta FromMinutes(int minutes); 42 static TimeDelta FromSeconds(int64_t seconds); 43 static TimeDelta FromMilliseconds(int64_t milliseconds); FromMicroseconds(int64_t microseconds)44 static TimeDelta FromMicroseconds(int64_t microseconds) { 45 return TimeDelta(microseconds); 46 } 47 static TimeDelta FromNanoseconds(int64_t nanoseconds); 48 49 // Returns the time delta in some unit. The F versions return a floating 50 // point value, the "regular" versions return a rounded-down value. 51 // 52 // InMillisecondsRoundedUp() instead returns an integer that is rounded up 53 // to the next full millisecond. 54 int InDays() const; 55 int InHours() const; 56 int InMinutes() const; 57 double InSecondsF() const; 58 int64_t InSeconds() const; 59 double InMillisecondsF() const; 60 int64_t InMilliseconds() const; 61 int64_t InMillisecondsRoundedUp() const; InMicroseconds()62 int64_t InMicroseconds() const { return delta_; } 63 int64_t InNanoseconds() const; 64 65 // Converts to/from Mach time specs. 66 static TimeDelta FromMachTimespec(struct mach_timespec ts); 67 struct mach_timespec ToMachTimespec() const; 68 69 // Converts to/from POSIX time specs. 70 static TimeDelta FromTimespec(struct timespec ts); 71 struct timespec ToTimespec() const; 72 73 TimeDelta& operator=(const TimeDelta& other) { 74 delta_ = other.delta_; 75 return *this; 76 } 77 78 // Computations with other deltas. 79 TimeDelta operator+(const TimeDelta& other) const { 80 return TimeDelta(delta_ + other.delta_); 81 } 82 TimeDelta operator-(const TimeDelta& other) const { 83 return TimeDelta(delta_ - other.delta_); 84 } 85 86 TimeDelta& operator+=(const TimeDelta& other) { 87 delta_ += other.delta_; 88 return *this; 89 } 90 TimeDelta& operator-=(const TimeDelta& other) { 91 delta_ -= other.delta_; 92 return *this; 93 } 94 TimeDelta operator-() const { 95 return TimeDelta(-delta_); 96 } 97 TimesOf(const TimeDelta & other)98 double TimesOf(const TimeDelta& other) const { 99 return static_cast<double>(delta_) / static_cast<double>(other.delta_); 100 } PercentOf(const TimeDelta & other)101 double PercentOf(const TimeDelta& other) const { 102 return TimesOf(other) * 100.0; 103 } 104 105 // Computations with ints, note that we only allow multiplicative operations 106 // with ints, and additive operations with other deltas. 107 TimeDelta operator*(int64_t a) const { 108 return TimeDelta(delta_ * a); 109 } 110 TimeDelta operator/(int64_t a) const { 111 return TimeDelta(delta_ / a); 112 } 113 TimeDelta& operator*=(int64_t a) { 114 delta_ *= a; 115 return *this; 116 } 117 TimeDelta& operator/=(int64_t a) { 118 delta_ /= a; 119 return *this; 120 } 121 int64_t operator/(const TimeDelta& other) const { 122 return delta_ / other.delta_; 123 } 124 125 // Comparison operators. 126 bool operator==(const TimeDelta& other) const { 127 return delta_ == other.delta_; 128 } 129 bool operator!=(const TimeDelta& other) const { 130 return delta_ != other.delta_; 131 } 132 bool operator<(const TimeDelta& other) const { 133 return delta_ < other.delta_; 134 } 135 bool operator<=(const TimeDelta& other) const { 136 return delta_ <= other.delta_; 137 } 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 145 private: 146 // Constructs a delta given the duration in microseconds. This is private 147 // to avoid confusion by callers with an integer constructor. Use 148 // FromSeconds, FromMilliseconds, etc. instead. TimeDelta(int64_t delta)149 explicit TimeDelta(int64_t delta) : delta_(delta) {} 150 151 // Delta in microseconds. 152 int64_t delta_; 153 }; 154 155 156 // ----------------------------------------------------------------------------- 157 // Time 158 // 159 // This class represents an absolute point in time, internally represented as 160 // microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970. 161 162 class Time final { 163 public: 164 static const int64_t kMillisecondsPerSecond = 1000; 165 static const int64_t kMicrosecondsPerMillisecond = 1000; 166 static const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * 167 kMillisecondsPerSecond; 168 static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; 169 static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; 170 static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * 24; 171 static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; 172 static const int64_t kNanosecondsPerMicrosecond = 1000; 173 static const int64_t kNanosecondsPerSecond = kNanosecondsPerMicrosecond * 174 kMicrosecondsPerSecond; 175 176 // Contains the NULL time. Use Time::Now() to get the current time. Time()177 Time() : us_(0) {} 178 179 // Returns true if the time object has not been initialized. IsNull()180 bool IsNull() const { return us_ == 0; } 181 182 // Returns true if the time object is the maximum time. IsMax()183 bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); } 184 185 // Returns the current time. Watch out, the system might adjust its clock 186 // in which case time will actually go backwards. We don't guarantee that 187 // times are increasing, or that two calls to Now() won't be the same. 188 static Time Now(); 189 190 // Returns the current time. Same as Now() except that this function always 191 // uses system time so that there are no discrepancies between the returned 192 // time and system time even on virtual environments including our test bot. 193 // For timing sensitive unittests, this function should be used. 194 static Time NowFromSystemTime(); 195 196 // Returns the time for epoch in Unix-like system (Jan 1, 1970). UnixEpoch()197 static Time UnixEpoch() { return Time(0); } 198 199 // Returns the maximum time, which should be greater than any reasonable time 200 // with which we might compare it. Max()201 static Time Max() { return Time(std::numeric_limits<int64_t>::max()); } 202 203 // Converts to/from internal values. The meaning of the "internal value" is 204 // completely up to the implementation, so it should be treated as opaque. FromInternalValue(int64_t value)205 static Time FromInternalValue(int64_t value) { 206 return Time(value); 207 } ToInternalValue()208 int64_t ToInternalValue() const { 209 return us_; 210 } 211 212 // Converts to/from POSIX time specs. 213 static Time FromTimespec(struct timespec ts); 214 struct timespec ToTimespec() const; 215 216 // Converts to/from POSIX time values. 217 static Time FromTimeval(struct timeval tv); 218 struct timeval ToTimeval() const; 219 220 // Converts to/from Windows file times. 221 static Time FromFiletime(struct _FILETIME ft); 222 struct _FILETIME ToFiletime() const; 223 224 // Converts to/from the Javascript convention for times, a number of 225 // milliseconds since the epoch: 226 static Time FromJsTime(double ms_since_epoch); 227 double ToJsTime() const; 228 229 Time& operator=(const Time& other) { 230 us_ = other.us_; 231 return *this; 232 } 233 234 // Compute the difference between two times. 235 TimeDelta operator-(const Time& other) const { 236 return TimeDelta::FromMicroseconds(us_ - other.us_); 237 } 238 239 // Modify by some time delta. 240 Time& operator+=(const TimeDelta& delta) { 241 us_ += delta.InMicroseconds(); 242 return *this; 243 } 244 Time& operator-=(const TimeDelta& delta) { 245 us_ -= delta.InMicroseconds(); 246 return *this; 247 } 248 249 // Return a new time modified by some delta. 250 Time operator+(const TimeDelta& delta) const { 251 return Time(us_ + delta.InMicroseconds()); 252 } 253 Time operator-(const TimeDelta& delta) const { 254 return Time(us_ - delta.InMicroseconds()); 255 } 256 257 // Comparison operators 258 bool operator==(const Time& other) const { 259 return us_ == other.us_; 260 } 261 bool operator!=(const Time& other) const { 262 return us_ != other.us_; 263 } 264 bool operator<(const Time& other) const { 265 return us_ < other.us_; 266 } 267 bool operator<=(const Time& other) const { 268 return us_ <= other.us_; 269 } 270 bool operator>(const Time& other) const { 271 return us_ > other.us_; 272 } 273 bool operator>=(const Time& other) const { 274 return us_ >= other.us_; 275 } 276 277 private: Time(int64_t us)278 explicit Time(int64_t us) : us_(us) {} 279 280 // Time in microseconds in UTC. 281 int64_t us_; 282 }; 283 284 std::ostream& operator<<(std::ostream&, const Time&); 285 286 inline Time operator+(const TimeDelta& delta, const Time& time) { 287 return time + delta; 288 } 289 290 291 // ----------------------------------------------------------------------------- 292 // TimeTicks 293 // 294 // This class represents an abstract time that is most of the time incrementing 295 // for use in measuring time durations. It is internally represented in 296 // microseconds. It can not be converted to a human-readable time, but is 297 // guaranteed not to decrease (if the user changes the computer clock, 298 // Time::Now() may actually decrease or jump). But note that TimeTicks may 299 // "stand still", for example if the computer suspended. 300 301 class TimeTicks final { 302 public: TimeTicks()303 TimeTicks() : ticks_(0) {} 304 305 // Platform-dependent tick count representing "right now." 306 // The resolution of this clock is ~1-15ms. Resolution varies depending 307 // on hardware/operating system configuration. 308 // This method never returns a null TimeTicks. 309 static TimeTicks Now(); 310 311 // Returns a platform-dependent high-resolution tick count. Implementation 312 // is hardware dependent and may or may not return sub-millisecond 313 // resolution. THIS CALL IS GENERALLY MUCH MORE EXPENSIVE THAN Now() AND 314 // SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED. 315 // This method never returns a null TimeTicks. 316 static TimeTicks HighResolutionNow(); 317 318 // Returns true if the high-resolution clock is working on this system. 319 static bool IsHighResolutionClockWorking(); 320 321 // Returns Linux kernel timestamp for generating profiler events. This method 322 // returns null TimeTicks if the kernel cannot provide the timestamps (e.g., 323 // on non-Linux OS or if the kernel module for timestamps is not loaded). 324 325 static TimeTicks KernelTimestampNow(); 326 static bool KernelTimestampAvailable(); 327 328 // Returns true if this object has not been initialized. IsNull()329 bool IsNull() const { return ticks_ == 0; } 330 331 // Converts to/from internal values. The meaning of the "internal value" is 332 // completely up to the implementation, so it should be treated as opaque. FromInternalValue(int64_t value)333 static TimeTicks FromInternalValue(int64_t value) { 334 return TimeTicks(value); 335 } ToInternalValue()336 int64_t ToInternalValue() const { 337 return ticks_; 338 } 339 340 TimeTicks& operator=(const TimeTicks other) { 341 ticks_ = other.ticks_; 342 return *this; 343 } 344 345 // Compute the difference between two times. 346 TimeDelta operator-(const TimeTicks other) const { 347 return TimeDelta::FromMicroseconds(ticks_ - other.ticks_); 348 } 349 350 // Modify by some time delta. 351 TimeTicks& operator+=(const TimeDelta& delta) { 352 ticks_ += delta.InMicroseconds(); 353 return *this; 354 } 355 TimeTicks& operator-=(const TimeDelta& delta) { 356 ticks_ -= delta.InMicroseconds(); 357 return *this; 358 } 359 360 // Return a new TimeTicks modified by some delta. 361 TimeTicks operator+(const TimeDelta& delta) const { 362 return TimeTicks(ticks_ + delta.InMicroseconds()); 363 } 364 TimeTicks operator-(const TimeDelta& delta) const { 365 return TimeTicks(ticks_ - delta.InMicroseconds()); 366 } 367 368 // Comparison operators 369 bool operator==(const TimeTicks& other) const { 370 return ticks_ == other.ticks_; 371 } 372 bool operator!=(const TimeTicks& other) const { 373 return ticks_ != other.ticks_; 374 } 375 bool operator<(const TimeTicks& other) const { 376 return ticks_ < other.ticks_; 377 } 378 bool operator<=(const TimeTicks& other) const { 379 return ticks_ <= other.ticks_; 380 } 381 bool operator>(const TimeTicks& other) const { 382 return ticks_ > other.ticks_; 383 } 384 bool operator>=(const TimeTicks& other) const { 385 return ticks_ >= other.ticks_; 386 } 387 388 private: 389 // Please use Now() to create a new object. This is for internal use 390 // and testing. Ticks is in microseconds. TimeTicks(int64_t ticks)391 explicit TimeTicks(int64_t ticks) : ticks_(ticks) {} 392 393 // Tick count in microseconds. 394 int64_t ticks_; 395 }; 396 397 inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) { 398 return ticks + delta; 399 } 400 401 } // namespace base 402 } // namespace v8 403 404 #endif // V8_BASE_PLATFORM_TIME_H_ 405