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