1 : /*
2 : * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : // Time represents an absolute point in time, internally represented as
8 : // microseconds (s/1,000,000) since a platform-dependent epoch. Each
9 : // platform's epoch, along with other system-dependent clock interface
10 : // routines, is defined in time_PLATFORM.cc.
11 : //
12 : // TimeDelta represents a duration of time, internally represented in
13 : // microseconds.
14 : //
15 : // TimeTicks represents an abstract time that is always incrementing for use
16 : // in measuring time durations. It is internally represented in microseconds.
17 : // It can not be converted to a human-readable time, but is guaranteed not to
18 : // decrease (if the user changes the computer clock, Time::Now() may actually
19 : // decrease or jump).
20 : //
21 : // These classes are represented as only a 64-bit value, so they can be
22 : // efficiently passed by value.
23 :
24 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_TIME_H__
25 : #define NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_TIME_H__
26 :
27 : namespace NaCl {
28 :
29 : class Time;
30 : class TimeTicks;
31 :
32 : // This unit test does a lot of manual time manipulation.
33 : class PageLoadTrackerUnitTest;
34 :
35 : // TimeDelta ------------------------------------------------------------------
36 :
37 : class TimeDelta {
38 : public:
39 : TimeDelta() : delta_(0) {
40 : }
41 :
42 : // Converts units of time to TimeDeltas.
43 : static TimeDelta FromDays(int64_t days);
44 : static TimeDelta FromHours(int64_t hours);
45 : static TimeDelta FromMinutes(int64_t minutes);
46 : static TimeDelta FromSeconds(int64_t secs);
47 : static TimeDelta FromMilliseconds(int64_t ms);
48 : static TimeDelta FromMicroseconds(int64_t us);
49 :
50 : // Returns the internal numeric value of the TimeDelta object. Please don't
51 : // use this and do arithmetic on it, as it is more error prone than using the
52 : // provided operators.
53 : int64_t ToInternalValue() const {
54 : return delta_;
55 : }
56 :
57 : // Returns the time delta in some unit. The F versions return a floating
58 : // point value, the "regular" versions return a rounded-down value.
59 : int InDays() const;
60 : double InSecondsF() const;
61 : int64_t InSeconds() const;
62 : double InMillisecondsF() const;
63 : int64_t InMilliseconds() const;
64 : int64_t InMicroseconds() const;
65 :
66 0 : TimeDelta& operator=(TimeDelta other) {
67 0 : delta_ = other.delta_;
68 0 : return *this;
69 0 : }
70 :
71 : // Computations with other deltas.
72 : TimeDelta operator+(TimeDelta other) const {
73 : return TimeDelta(delta_ + other.delta_);
74 : }
75 : TimeDelta operator-(TimeDelta other) const {
76 : return TimeDelta(delta_ - other.delta_);
77 : }
78 :
79 : TimeDelta& operator+=(TimeDelta other) {
80 : delta_ += other.delta_;
81 : return *this;
82 : }
83 : TimeDelta& operator-=(TimeDelta other) {
84 : delta_ -= other.delta_;
85 : return *this;
86 : }
87 : TimeDelta operator-() const {
88 : return TimeDelta(-delta_);
89 : }
90 :
91 : // Computations with ints, note that we only allow multiplicative operations
92 : // with ints, and additive operations with other deltas.
93 : TimeDelta operator*(int64_t a) const {
94 : return TimeDelta(delta_ * a);
95 : }
96 : TimeDelta operator/(int64_t a) const {
97 : return TimeDelta(delta_ / a);
98 : }
99 : TimeDelta& operator*=(int64_t a) {
100 : delta_ *= a;
101 : return *this;
102 : }
103 : TimeDelta& operator/=(int64_t a) {
104 : delta_ /= a;
105 : return *this;
106 : }
107 : int64_t operator/(TimeDelta a) const {
108 : return delta_ / a.delta_;
109 : }
110 :
111 : // Defined below because it depends on the definition of the other classes.
112 : Time operator+(Time t) const;
113 : TimeTicks operator+(TimeTicks t) const;
114 :
115 : // Comparison operators.
116 : bool operator==(TimeDelta other) const {
117 : return delta_ == other.delta_;
118 : }
119 : bool operator!=(TimeDelta other) const {
120 : return delta_ != other.delta_;
121 : }
122 : bool operator<(TimeDelta other) const {
123 : return delta_ < other.delta_;
124 : }
125 : bool operator<=(TimeDelta other) const {
126 : return delta_ <= other.delta_;
127 : }
128 : bool operator>(TimeDelta other) const {
129 : return delta_ > other.delta_;
130 : }
131 : bool operator>=(TimeDelta other) const {
132 : return delta_ >= other.delta_;
133 : }
134 :
135 : private:
136 : friend class Time;
137 : friend class TimeTicks;
138 : friend TimeDelta operator*(int64_t a, TimeDelta td);
139 :
140 : // Constructs a delta given the duration in microseconds. This is private
141 : // to avoid confusion by callers with an integer constructor. Use
142 : // FromSeconds, FromMilliseconds, etc. instead.
143 2 : explicit TimeDelta(int64_t delta_us) : delta_(delta_us) {
144 2 : }
145 :
146 : // Delta in microseconds.
147 : int64_t delta_;
148 : };
149 :
150 : inline TimeDelta operator*(int64_t a, TimeDelta td) {
151 : return TimeDelta(a * td.delta_);
152 : }
153 :
154 : // Time -----------------------------------------------------------------------
155 :
156 : // Represents a wall clock time.
157 : class Time {
158 : public:
159 : static const int64_t kMillisecondsPerSecond = 1000;
160 : static const int64_t kMicrosecondsPerMillisecond = 1000;
161 : static const int64_t kNanosecondsPerMicrosecond = 1000;
162 : static const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond *
163 : kMillisecondsPerSecond;
164 : static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
165 : static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60;
166 : static const int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * 24;
167 : static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7;
168 :
169 : // Represents an exploded time that can be formatted nicely. This is kind of
170 : // like the Win32 SYSTEMTIME structure or the Unix "struct tm" with a few
171 : // additions and changes to prevent errors.
172 : struct Exploded {
173 : int year; // Four digit year "2007"
174 : int month; // 1-based month (values 1 = January, etc.)
175 : int day_of_week; // 0-based day of week (0 = Sunday, etc.)
176 : int day_of_month; // 1-based day of month (1-31)
177 : int hour; // Hour within the current day (0-23)
178 : int minute; // Minute within the current hour (0-59)
179 : int second; // Second within the current minute (0-59 plus leap
180 : // seconds which may take it up to 60).
181 : int millisecond; // Milliseconds within the current second (0-999)
182 : };
183 :
184 : // Contains the NULL time. Use Time::Now() to get the current time.
185 0 : explicit Time() : us_(0) {
186 0 : }
187 :
188 : // Returns true if the time object has not been initialized.
189 : bool is_null() const {
190 : return us_ == 0;
191 : }
192 :
193 : // Returns the current time. Watch out, the system might adjust its clock
194 : // in which case time will actually go backwards. We don't guarantee that
195 : // times are increasing, or that two calls to Now() won't be the same.
196 : static Time Now();
197 :
198 : // Converts to/from time_t in UTC and a Time class.
199 : // TODO(brettw) this should be removed once everybody starts using the |Time|
200 : // class.
201 : static Time FromTimeT(time_t tt);
202 : time_t ToTimeT() const;
203 :
204 : // Converts time to a double which is the number of seconds since epoch
205 : // (Jan 1, 1970). Webkit uses this format to represent time.
206 : double ToDoubleT() const;
207 :
208 : #if NACL_WINDOWS
209 : static Time FromFileTime(FILETIME ft);
210 : FILETIME ToFileTime() const;
211 : #endif
212 :
213 : // Converts an exploded structure representing either the local time or UTC
214 : // into a Time class.
215 : static Time FromUTCExploded(const Exploded& exploded) {
216 : return FromExploded(false, exploded);
217 : }
218 0 : static Time FromLocalExploded(const Exploded& exploded) {
219 0 : return FromExploded(true, exploded);
220 0 : }
221 :
222 : // Converts an integer value representing Time to a class. This is used
223 : // when deserializing a |Time| structure, using a value known to be
224 : // compatible. It is not provided as a constructor because the integer type
225 : // may be unclear from the perspective of a caller.
226 : static Time FromInternalValue(int64_t us) {
227 : return Time(us);
228 : }
229 :
230 : // Converts a string representation of time to a Time object.
231 : // An example of a time string which is converted is as below:-
232 : // "Tue, 15 Nov 1994 12:45:26 GMT". If the timezone is not specified
233 : // in the input string, we assume local time.
234 : // TODO(iyengar) Move the FromString/FromTimeT/ToTimeT/FromFileTime to
235 : // a new time converter class.
236 : // NOTE(gregoryd) - removed to avoid the need in string suppport
237 : // static bool FromString(const wchar_t* time_string, Time* parsed_time);
238 :
239 : // For serializing, use FromInternalValue to reconstitute. Please don't use
240 : // this and do arithmetic on it, as it is more error prone than using the
241 : // provided operators.
242 : int64_t ToInternalValue() const {
243 : return us_;
244 : }
245 :
246 : // Fills the given exploded structure with either the local time or UTC from
247 : // this time structure (containing UTC).
248 : void UTCExplode(Exploded* exploded) const {
249 : return Explode(false, exploded);
250 : }
251 0 : void LocalExplode(Exploded* exploded) const {
252 0 : return Explode(true, exploded);
253 0 : }
254 :
255 : // Rounds this time down to the nearest day in local time. It will represent
256 : // midnight on that day.
257 : Time LocalMidnight() const;
258 :
259 : Time& operator=(Time other) {
260 : us_ = other.us_;
261 : return *this;
262 : }
263 :
264 : // Compute the difference between two times.
265 : TimeDelta operator-(Time other) const {
266 : return TimeDelta(us_ - other.us_);
267 : }
268 :
269 : // Modify by some time delta.
270 : Time& operator+=(TimeDelta delta) {
271 : us_ += delta.delta_;
272 : return *this;
273 : }
274 : Time& operator-=(TimeDelta delta) {
275 : us_ -= delta.delta_;
276 : return *this;
277 : }
278 :
279 : // Return a new time modified by some delta.
280 : Time operator+(TimeDelta delta) const {
281 : return Time(us_ + delta.delta_);
282 : }
283 : Time operator-(TimeDelta delta) const {
284 : return Time(us_ - delta.delta_);
285 : }
286 :
287 : // Comparison operators
288 : bool operator==(Time other) const {
289 : return us_ == other.us_;
290 : }
291 : bool operator!=(Time other) const {
292 : return us_ != other.us_;
293 : }
294 : bool operator<(Time other) const {
295 : return us_ < other.us_;
296 : }
297 : bool operator<=(Time other) const {
298 : return us_ <= other.us_;
299 : }
300 : bool operator>(Time other) const {
301 : return us_ > other.us_;
302 : }
303 : bool operator>=(Time other) const {
304 : return us_ >= other.us_;
305 : }
306 :
307 : private:
308 : friend class TimeDelta;
309 :
310 : // Platform-dependent wall clock interface
311 : static int64_t CurrentWallclockMicroseconds();
312 :
313 : // Initialize or resynchronize the clock.
314 : static void InitializeClock();
315 :
316 : // Explodes the given time to either local time |is_local = true| or UTC
317 : // |is_local = false|.
318 : void Explode(bool is_local, Exploded* exploded) const;
319 :
320 : // Unexplodes a given time assuming the source is either local time
321 : // |is_local = true| or UTC |is_local = false|.
322 : static Time FromExploded(bool is_local, const Exploded& exploded);
323 :
324 0 : explicit Time(int64_t us) : us_(us) {
325 0 : }
326 :
327 : // The representation of Jan 1, 1970 UTC in microseconds since the
328 : // platform-dependent epoch.
329 : static const int64_t kTimeTToMicrosecondsOffset;
330 :
331 : // Time in microseconds in UTC.
332 : int64_t us_;
333 :
334 : // The initial time sampled via this API.
335 : static int64_t initial_time_;
336 :
337 : // The initial clock counter sampled via this API.
338 : static TimeTicks initial_ticks_;
339 : };
340 :
341 0 : inline Time TimeDelta::operator+(Time t) const {
342 0 : return Time(t.us_ + delta_);
343 0 : }
344 :
345 : // TimeTicks ------------------------------------------------------------------
346 :
347 : class TimeTicks {
348 : public:
349 36 : TimeTicks() : ticks_(0) {
350 36 : }
351 :
352 : // TODO(gregoryd): made this constructor public, but might undo this change
353 : // when we cleanup the time-handling code.
354 0 : explicit TimeTicks(int64_t ticks) : ticks_(ticks) {
355 0 : }
356 :
357 : // Platform-dependent tick count representing "right now."
358 : // The resolution of this clock is ~1-5ms. Resolution varies depending
359 : // on hardware/operating system configuration.
360 : static TimeTicks Now();
361 :
362 : // Returns a platform-dependent high-resolution tick count. IT IS BROKEN ON
363 : // SOME HARDWARE and is designed to be used for profiling and perf testing
364 : // only (see the impl for more information).
365 : static TimeTicks UnreliableHighResNow();
366 :
367 :
368 : // Returns true if this object has not been initialized.
369 : bool is_null() const {
370 : return ticks_ == 0;
371 : }
372 :
373 0 : TimeTicks& operator=(TimeTicks other) {
374 0 : ticks_ = other.ticks_;
375 0 : return *this;
376 0 : }
377 :
378 : // Compute the difference between two times.
379 0 : TimeDelta operator-(TimeTicks other) const {
380 0 : return TimeDelta(ticks_ - other.ticks_);
381 0 : }
382 :
383 : // Modify by some time delta.
384 : TimeTicks& operator+=(TimeDelta delta) {
385 : ticks_ += delta.delta_;
386 : return *this;
387 : }
388 : TimeTicks& operator-=(TimeDelta delta) {
389 : ticks_ -= delta.delta_;
390 : return *this;
391 : }
392 :
393 : // Return a new TimeTicks modified by some delta.
394 : TimeTicks operator+(TimeDelta delta) const {
395 : return TimeTicks(ticks_ + delta.delta_);
396 : }
397 : TimeTicks operator-(TimeDelta delta) const {
398 : return TimeTicks(ticks_ - delta.delta_);
399 : }
400 :
401 : // Comparison operators
402 : bool operator==(TimeTicks other) const {
403 : return ticks_ == other.ticks_;
404 : }
405 : bool operator!=(TimeTicks other) const {
406 : return ticks_ != other.ticks_;
407 : }
408 : bool operator<(TimeTicks other) const {
409 : return ticks_ < other.ticks_;
410 : }
411 : bool operator<=(TimeTicks other) const {
412 : return ticks_ <= other.ticks_;
413 : }
414 : bool operator>(TimeTicks other) const {
415 : return ticks_ > other.ticks_;
416 : }
417 : bool operator>=(TimeTicks other) const {
418 : return ticks_ >= other.ticks_;
419 : }
420 : #if NACL_LINUX || NACL_OSX || defined(__native_client__)
421 : void InitTimespec(struct timespec *ts) const;
422 : #endif
423 0 : int64_t ticks_for_testing() const { return ticks_; }
424 : protected:
425 : friend class TimeDelta;
426 : friend class PageLoadTrackerUnitTest;
427 :
428 :
429 : // Tick count in microseconds.
430 : int64_t ticks_;
431 :
432 : #if NACL_WINDOWS
433 : // The function to use for counting ticks.
434 : typedef int (__stdcall *TickFunction)(void);
435 : static TickFunction tick_function_;
436 : #endif
437 : };
438 :
439 : inline TimeTicks TimeDelta::operator+(TimeTicks t) const {
440 : return TimeTicks(t.ticks_ + delta_);
441 : }
442 :
443 : } // namespace NaCl
444 :
445 : #endif /* NATIVE_CLIENT_SRC_TRUSTED_PLATFORM_TIME_H__ */
|