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 : #include "native_client/src/include/portability.h"
8 :
9 : #include "native_client/src/shared/platform/win/time.h"
10 :
11 :
12 : namespace {
13 :
14 : // Time between resampling the un-granular clock for this API. 60 seconds.
15 : const int kMaxMillisecondsToAvoidDrift =
16 : 60 * NaCl::Time::kMillisecondsPerSecond;
17 :
18 : } // namespace
19 :
20 : // TimeDelta ------------------------------------------------------------------
21 :
22 : // static
23 0 : NaCl::TimeDelta NaCl::TimeDelta::FromDays(int64_t days) {
24 0 : return TimeDelta(days * Time::kMicrosecondsPerDay);
25 0 : }
26 :
27 : // static
28 0 : NaCl::TimeDelta NaCl::TimeDelta::FromHours(int64_t hours) {
29 0 : return TimeDelta(hours * Time::kMicrosecondsPerHour);
30 0 : }
31 :
32 : // static
33 0 : NaCl::TimeDelta NaCl::TimeDelta::FromMinutes(int64_t minutes) {
34 0 : return TimeDelta(minutes * Time::kMicrosecondsPerMinute);
35 0 : }
36 :
37 : // static
38 0 : NaCl::TimeDelta NaCl::TimeDelta::FromSeconds(int64_t secs) {
39 0 : return TimeDelta(secs * Time::kMicrosecondsPerSecond);
40 0 : }
41 :
42 : // static
43 2 : NaCl::TimeDelta NaCl::TimeDelta::FromMilliseconds(int64_t ms) {
44 2 : return TimeDelta(ms * Time::kMicrosecondsPerMillisecond);
45 2 : }
46 :
47 : // static
48 0 : NaCl::TimeDelta NaCl::TimeDelta::FromMicroseconds(int64_t us) {
49 0 : return TimeDelta(us);
50 0 : }
51 :
52 0 : int NaCl::TimeDelta::InDays() const {
53 0 : return static_cast<int>(delta_ / Time::kMicrosecondsPerDay);
54 0 : }
55 :
56 0 : double NaCl::TimeDelta::InSecondsF() const {
57 0 : return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond;
58 0 : }
59 :
60 0 : int64_t NaCl::TimeDelta::InSeconds() const {
61 0 : return delta_ / Time::kMicrosecondsPerSecond;
62 0 : }
63 :
64 0 : double NaCl::TimeDelta::InMillisecondsF() const {
65 0 : return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond;
66 0 : }
67 :
68 2 : int64_t NaCl::TimeDelta::InMilliseconds() const {
69 2 : return delta_ / Time::kMicrosecondsPerMillisecond;
70 2 : }
71 :
72 0 : int64_t NaCl::TimeDelta::InMicroseconds() const {
73 0 : return delta_;
74 0 : }
75 :
76 : // Time -----------------------------------------------------------------------
77 :
78 : int64_t NaCl::Time::initial_time_ = 0;
79 36 : NaCl::TimeTicks NaCl::Time::initial_ticks_;
80 :
81 : // static
82 0 : void NaCl::Time::InitializeClock() {
83 0 : initial_ticks_ = TimeTicks::Now();
84 0 : initial_time_ = CurrentWallclockMicroseconds();
85 0 : }
86 :
87 : // static
88 0 : NaCl::Time NaCl::Time::Now() {
89 0 : if (initial_time_ == 0)
90 0 : InitializeClock();
91 :
92 : // We implement time using the high-resolution timers so that we can get
93 : // timeouts which are smaller than 10-15ms. If we just used
94 : // CurrentWallclockMicroseconds(), we'd have the less-granular timer.
95 : //
96 : // To make this work, we initialize the clock (initial_time) and the
97 : // counter (initial_ctr). To compute the initial time, we can check
98 : // the number of ticks that have elapsed, and compute the delta.
99 : //
100 : // To avoid any drift, we periodically resync the counters to the system
101 : // clock.
102 0 : while (true) {
103 0 : TimeTicks ticks = TimeTicks::Now();
104 :
105 : // Calculate the time elapsed since we started our timer
106 0 : TimeDelta elapsed = ticks - initial_ticks_;
107 :
108 : // Check if enough time has elapsed that we need to resync the clock.
109 0 : if (elapsed.InMilliseconds() > kMaxMillisecondsToAvoidDrift) {
110 0 : InitializeClock();
111 0 : continue;
112 : }
113 :
114 0 : return elapsed + Time(initial_time_);
115 : }
116 0 : }
117 :
118 : // static
119 0 : NaCl::Time NaCl::Time::FromTimeT(time_t tt) {
120 0 : if (tt == 0)
121 0 : return Time(); // Preserve 0 so we can tell it doesn't exist.
122 0 : return NaCl::Time((tt * kMicrosecondsPerSecond) + kTimeTToMicrosecondsOffset);
123 0 : }
124 :
125 0 : time_t NaCl::Time::ToTimeT() const {
126 0 : if (us_ == 0)
127 0 : return 0; // Preserve 0 so we can tell it doesn't exist.
128 0 : return (us_ - kTimeTToMicrosecondsOffset) / kMicrosecondsPerSecond;
129 0 : }
130 :
131 0 : double NaCl::Time::ToDoubleT() const {
132 0 : if (us_ == 0)
133 0 : return 0; // Preserve 0 so we can tell it doesn't exist.
134 : return (static_cast<double>(us_ - kTimeTToMicrosecondsOffset) /
135 0 : static_cast<double>(kMicrosecondsPerSecond));
136 0 : }
137 :
138 0 : NaCl::Time NaCl::Time::LocalMidnight() const {
139 : Exploded exploded;
140 0 : LocalExplode(&exploded);
141 0 : exploded.hour = 0;
142 0 : exploded.minute = 0;
143 0 : exploded.second = 0;
144 0 : exploded.millisecond = 0;
145 0 : return FromLocalExploded(exploded);
146 0 : }
|