| 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 |