OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 // Windows Timer Primer | 6 // Windows Timer Primer |
7 // | 7 // |
8 // A good article: http://www.ddj.com/windows/184416651 | 8 // A good article: http://www.ddj.com/windows/184416651 |
9 // A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 | 9 // A good mozilla bug: http://bugzilla.mozilla.org/show_bug.cgi?id=363258 |
10 // | 10 // |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; | 81 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; |
82 | 82 |
83 int64 initial_time = 0; | 83 int64 initial_time = 0; |
84 TimeTicks initial_ticks; | 84 TimeTicks initial_ticks; |
85 | 85 |
86 void InitializeClock() { | 86 void InitializeClock() { |
87 initial_ticks = TimeTicks::Now(); | 87 initial_ticks = TimeTicks::Now(); |
88 initial_time = CurrentWallclockMicroseconds(); | 88 initial_time = CurrentWallclockMicroseconds(); |
89 } | 89 } |
90 | 90 |
| 91 class HighResolutionTimerManager : public base::SystemMonitor::PowerObserver { |
| 92 public: |
| 93 ~HighResolutionTimerManager() { |
| 94 StopMonitoring(); |
| 95 UseHiResClock(false); |
| 96 } |
| 97 |
| 98 void Enable() { |
| 99 StopMonitoring(); |
| 100 UseHiResClock(true); |
| 101 } |
| 102 |
| 103 void StartMonitoring() { |
| 104 if (is_monitoring_) |
| 105 return; |
| 106 is_monitoring_ = true; |
| 107 base::SystemMonitor* system = base::SystemMonitor::Get(); |
| 108 DCHECK(system); |
| 109 system->AddObserver(this); |
| 110 UseHiResClock(!system->BatteryPower()); |
| 111 } |
| 112 |
| 113 void StopMonitoring() { |
| 114 if (!is_monitoring_) |
| 115 return; |
| 116 is_monitoring_ = false; |
| 117 base::SystemMonitor* monitor = base::SystemMonitor::Get(); |
| 118 if (monitor) |
| 119 monitor->RemoveObserver(this); |
| 120 } |
| 121 |
| 122 // Interfaces for monitoring Power changes. |
| 123 void OnPowerStateChange(base::SystemMonitor* system) { |
| 124 UseHiResClock(!system->BatteryPower()); |
| 125 } |
| 126 |
| 127 void OnSuspend(base::SystemMonitor* system) {} |
| 128 void OnResume(base::SystemMonitor* system) {} |
| 129 |
| 130 private: |
| 131 HighResolutionTimerManager() |
| 132 : is_monitoring_(false), |
| 133 hi_res_clock_enabled_(false) { |
| 134 } |
| 135 friend struct DefaultSingletonTraits<HighResolutionTimerManager>; |
| 136 |
| 137 // Enable or disable the faster multimedia timer. |
| 138 void UseHiResClock(bool enabled) { |
| 139 if (enabled == hi_res_clock_enabled_) |
| 140 return; |
| 141 if (enabled) |
| 142 timeBeginPeriod(1); |
| 143 else |
| 144 timeEndPeriod(1); |
| 145 hi_res_clock_enabled_ = enabled; |
| 146 } |
| 147 |
| 148 bool is_monitoring_; |
| 149 bool hi_res_clock_enabled_; |
| 150 |
| 151 DISALLOW_COPY_AND_ASSIGN(HighResolutionTimerManager); |
| 152 }; |
| 153 |
91 } // namespace | 154 } // namespace |
92 | 155 |
93 // Time ----------------------------------------------------------------------- | 156 // Time ----------------------------------------------------------------------- |
94 | 157 |
95 // The internal representation of Time uses FILETIME, whose epoch is 1601-01-01 | 158 // The internal representation of Time uses FILETIME, whose epoch is 1601-01-01 |
96 // 00:00:00 UTC. ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the | 159 // 00:00:00 UTC. ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the |
97 // number of leap year days between 1601 and 1970: (1970-1601)/4 excluding | 160 // number of leap year days between 1601 and 1970: (1970-1601)/4 excluding |
98 // 1700, 1800, and 1900. | 161 // 1700, 1800, and 1900. |
99 // static | 162 // static |
100 const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000); | 163 const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 return Time(FileTimeToMicroseconds(ft)); | 205 return Time(FileTimeToMicroseconds(ft)); |
143 } | 206 } |
144 | 207 |
145 FILETIME Time::ToFileTime() const { | 208 FILETIME Time::ToFileTime() const { |
146 FILETIME utc_ft; | 209 FILETIME utc_ft; |
147 MicrosecondsToFileTime(us_, &utc_ft); | 210 MicrosecondsToFileTime(us_, &utc_ft); |
148 return utc_ft; | 211 return utc_ft; |
149 } | 212 } |
150 | 213 |
151 // static | 214 // static |
| 215 void Time::StartSystemMonitorObserver() { |
| 216 Singleton<HighResolutionTimerManager>()->StartMonitoring(); |
| 217 } |
| 218 |
| 219 // static |
| 220 void Time::EnableHiResClockForTests() { |
| 221 Singleton<HighResolutionTimerManager>()->Enable(); |
| 222 } |
| 223 |
| 224 // static |
152 Time Time::FromExploded(bool is_local, const Exploded& exploded) { | 225 Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
153 // Create the system struct representing our exploded time. It will either be | 226 // Create the system struct representing our exploded time. It will either be |
154 // in local time or UTC. | 227 // in local time or UTC. |
155 SYSTEMTIME st; | 228 SYSTEMTIME st; |
156 st.wYear = exploded.year; | 229 st.wYear = exploded.year; |
157 st.wMonth = exploded.month; | 230 st.wMonth = exploded.month; |
158 st.wDayOfWeek = exploded.day_of_week; | 231 st.wDayOfWeek = exploded.day_of_week; |
159 st.wDay = exploded.day_of_month; | 232 st.wDay = exploded.day_of_month; |
160 st.wHour = exploded.hour; | 233 st.wHour = exploded.hour; |
161 st.wMinute = exploded.minute; | 234 st.wMinute = exploded.minute; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 } | 293 } |
221 | 294 |
222 | 295 |
223 DWORD (*tick_function)(void) = &timeGetTimeWrapper; | 296 DWORD (*tick_function)(void) = &timeGetTimeWrapper; |
224 | 297 |
225 // We use timeGetTime() to implement TimeTicks::Now(). This can be problematic | 298 // We use timeGetTime() to implement TimeTicks::Now(). This can be problematic |
226 // because it returns the number of milliseconds since Windows has started, | 299 // because it returns the number of milliseconds since Windows has started, |
227 // which will roll over the 32-bit value every ~49 days. We try to track | 300 // which will roll over the 32-bit value every ~49 days. We try to track |
228 // rollover ourselves, which works if TimeTicks::Now() is called at least every | 301 // rollover ourselves, which works if TimeTicks::Now() is called at least every |
229 // 49 days. | 302 // 49 days. |
230 class NowSingleton : public base::SystemMonitor::PowerObserver { | 303 class NowSingleton { |
231 public: | 304 public: |
232 NowSingleton() | 305 NowSingleton() |
233 : rollover_(TimeDelta::FromMilliseconds(0)), | 306 : rollover_(TimeDelta::FromMilliseconds(0)), |
234 last_seen_(0), | 307 last_seen_(0) { |
235 hi_res_clock_enabled_(false) { | |
236 base::SystemMonitor* system = base::SystemMonitor::Get(); | |
237 system->AddObserver(this); | |
238 UseHiResClock(!system->BatteryPower()); | |
239 } | 308 } |
240 | 309 |
241 ~NowSingleton() { | 310 ~NowSingleton() { |
242 UseHiResClock(false); | |
243 base::SystemMonitor* monitor = base::SystemMonitor::Get(); | |
244 if (monitor) | |
245 monitor->RemoveObserver(this); | |
246 } | 311 } |
247 | 312 |
248 TimeDelta Now() { | 313 TimeDelta Now() { |
249 AutoLock locked(lock_); | 314 AutoLock locked(lock_); |
250 // We should hold the lock while calling tick_function to make sure that | 315 // We should hold the lock while calling tick_function to make sure that |
251 // we keep our last_seen_ stay correctly in sync. | 316 // we keep our last_seen_ stay correctly in sync. |
252 DWORD now = tick_function(); | 317 DWORD now = tick_function(); |
253 if (now < last_seen_) | 318 if (now < last_seen_) |
254 rollover_ += TimeDelta::FromMilliseconds(0x100000000I64); // ~49.7 days. | 319 rollover_ += TimeDelta::FromMilliseconds(0x100000000I64); // ~49.7 days. |
255 last_seen_ = now; | 320 last_seen_ = now; |
256 return TimeDelta::FromMilliseconds(now) + rollover_; | 321 return TimeDelta::FromMilliseconds(now) + rollover_; |
257 } | 322 } |
258 | 323 |
259 // Interfaces for monitoring Power changes. | |
260 void OnPowerStateChange(base::SystemMonitor* system) { | |
261 UseHiResClock(!system->BatteryPower()); | |
262 } | |
263 | |
264 void OnSuspend(base::SystemMonitor* system) {} | |
265 void OnResume(base::SystemMonitor* system) {} | |
266 | |
267 private: | 324 private: |
268 // Enable or disable the faster multimedia timer. | |
269 void UseHiResClock(bool enabled) { | |
270 if (enabled == hi_res_clock_enabled_) | |
271 return; | |
272 if (enabled) | |
273 timeBeginPeriod(1); | |
274 else | |
275 timeEndPeriod(1); | |
276 hi_res_clock_enabled_ = enabled; | |
277 } | |
278 | |
279 Lock lock_; // To protected last_seen_ and rollover_. | 325 Lock lock_; // To protected last_seen_ and rollover_. |
280 TimeDelta rollover_; // Accumulation of time lost due to rollover. | 326 TimeDelta rollover_; // Accumulation of time lost due to rollover. |
281 DWORD last_seen_; // The last timeGetTime value we saw, to detect rollover. | 327 DWORD last_seen_; // The last timeGetTime value we saw, to detect rollover. |
282 bool hi_res_clock_enabled_; | |
283 | 328 |
284 DISALLOW_COPY_AND_ASSIGN(NowSingleton); | 329 DISALLOW_COPY_AND_ASSIGN(NowSingleton); |
285 }; | 330 }; |
286 | 331 |
287 // Overview of time counters: | 332 // Overview of time counters: |
288 // (1) CPU cycle counter. (Retrieved via RDTSC) | 333 // (1) CPU cycle counter. (Retrieved via RDTSC) |
289 // The CPU counter provides the highest resolution time stamp and is the least | 334 // The CPU counter provides the highest resolution time stamp and is the least |
290 // expensive to retrieve. However, the CPU counter is unreliable and should not | 335 // expensive to retrieve. However, the CPU counter is unreliable and should not |
291 // be used in production. Its biggest issue is that it is per processor and it | 336 // be used in production. Its biggest issue is that it is per processor and it |
292 // is not synchronized between processors. Also, on some computers, the counters | 337 // is not synchronized between processors. Also, on some computers, the counters |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 | 440 |
396 // static | 441 // static |
397 TimeTicks TimeTicks::Now() { | 442 TimeTicks TimeTicks::Now() { |
398 return TimeTicks() + Singleton<NowSingleton>::get()->Now(); | 443 return TimeTicks() + Singleton<NowSingleton>::get()->Now(); |
399 } | 444 } |
400 | 445 |
401 // static | 446 // static |
402 TimeTicks TimeTicks::HighResNow() { | 447 TimeTicks TimeTicks::HighResNow() { |
403 return TimeTicks() + Singleton<HighResNowSingleton>::get()->Now(); | 448 return TimeTicks() + Singleton<HighResNowSingleton>::get()->Now(); |
404 } | 449 } |
OLD | NEW |