OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 27 matching lines...) Expand all Loading... |
38 | 38 |
39 #pragma comment(lib, "winmm.lib") | 39 #pragma comment(lib, "winmm.lib") |
40 #include <windows.h> | 40 #include <windows.h> |
41 #include <mmsystem.h> | 41 #include <mmsystem.h> |
42 | 42 |
43 #include "base/basictypes.h" | 43 #include "base/basictypes.h" |
44 #include "base/lock.h" | 44 #include "base/lock.h" |
45 #include "base/logging.h" | 45 #include "base/logging.h" |
46 #include "base/cpu.h" | 46 #include "base/cpu.h" |
47 #include "base/singleton.h" | 47 #include "base/singleton.h" |
48 #include "base/system_monitor.h" | |
49 | 48 |
50 using base::Time; | 49 using base::Time; |
51 using base::TimeDelta; | 50 using base::TimeDelta; |
52 using base::TimeTicks; | 51 using base::TimeTicks; |
53 | 52 |
54 namespace { | 53 namespace { |
55 | 54 |
56 // From MSDN, FILETIME "Contains a 64-bit value representing the number of | 55 // From MSDN, FILETIME "Contains a 64-bit value representing the number of |
57 // 100-nanosecond intervals since January 1, 1601 (UTC)." | 56 // 100-nanosecond intervals since January 1, 1601 (UTC)." |
58 int64 FileTimeToMicroseconds(const FILETIME& ft) { | 57 int64 FileTimeToMicroseconds(const FILETIME& ft) { |
(...skipping 22 matching lines...) Expand all Loading... |
81 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; | 80 const int kMaxMillisecondsToAvoidDrift = 60 * Time::kMillisecondsPerSecond; |
82 | 81 |
83 int64 initial_time = 0; | 82 int64 initial_time = 0; |
84 TimeTicks initial_ticks; | 83 TimeTicks initial_ticks; |
85 | 84 |
86 void InitializeClock() { | 85 void InitializeClock() { |
87 initial_ticks = TimeTicks::Now(); | 86 initial_ticks = TimeTicks::Now(); |
88 initial_time = CurrentWallclockMicroseconds(); | 87 initial_time = CurrentWallclockMicroseconds(); |
89 } | 88 } |
90 | 89 |
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_monitor = base::SystemMonitor::Get(); | |
108 system_monitor->AddObserver(this); | |
109 UseHiResClock(!system_monitor->BatteryPower()); | |
110 } | |
111 | |
112 void StopMonitoring() { | |
113 if (!is_monitoring_) | |
114 return; | |
115 is_monitoring_ = false; | |
116 base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); | |
117 if (system_monitor) | |
118 system_monitor->RemoveObserver(this); | |
119 } | |
120 | |
121 // Interfaces for monitoring Power changes. | |
122 void OnPowerStateChange(bool on_battery_power) { | |
123 UseHiResClock(!on_battery_power); | |
124 } | |
125 | |
126 private: | |
127 HighResolutionTimerManager() | |
128 : is_monitoring_(false), | |
129 hi_res_clock_enabled_(false) { | |
130 } | |
131 friend struct DefaultSingletonTraits<HighResolutionTimerManager>; | |
132 | |
133 // Enable or disable the faster multimedia timer. | |
134 void UseHiResClock(bool enabled) { | |
135 if (enabled == hi_res_clock_enabled_) | |
136 return; | |
137 if (enabled) | |
138 timeBeginPeriod(1); | |
139 else | |
140 timeEndPeriod(1); | |
141 hi_res_clock_enabled_ = enabled; | |
142 } | |
143 | |
144 bool is_monitoring_; | |
145 bool hi_res_clock_enabled_; | |
146 | |
147 DISALLOW_COPY_AND_ASSIGN(HighResolutionTimerManager); | |
148 }; | |
149 | |
150 } // namespace | 90 } // namespace |
151 | 91 |
152 // Time ----------------------------------------------------------------------- | 92 // Time ----------------------------------------------------------------------- |
153 | 93 |
154 // The internal representation of Time uses FILETIME, whose epoch is 1601-01-01 | 94 // The internal representation of Time uses FILETIME, whose epoch is 1601-01-01 |
155 // 00:00:00 UTC. ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the | 95 // 00:00:00 UTC. ((1970-1601)*365+89)*24*60*60*1000*1000, where 89 is the |
156 // number of leap year days between 1601 and 1970: (1970-1601)/4 excluding | 96 // number of leap year days between 1601 and 1970: (1970-1601)/4 excluding |
157 // 1700, 1800, and 1900. | 97 // 1700, 1800, and 1900. |
158 // static | 98 // static |
159 const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000); | 99 const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 return Time(FileTimeToMicroseconds(ft)); | 141 return Time(FileTimeToMicroseconds(ft)); |
202 } | 142 } |
203 | 143 |
204 FILETIME Time::ToFileTime() const { | 144 FILETIME Time::ToFileTime() const { |
205 FILETIME utc_ft; | 145 FILETIME utc_ft; |
206 MicrosecondsToFileTime(us_, &utc_ft); | 146 MicrosecondsToFileTime(us_, &utc_ft); |
207 return utc_ft; | 147 return utc_ft; |
208 } | 148 } |
209 | 149 |
210 // static | 150 // static |
211 void Time::StartSystemMonitorObserver() { | 151 bool Time::UseHighResolutionTimer(bool use) { |
212 Singleton<HighResolutionTimerManager>()->StartMonitoring(); | 152 // TODO(mbelshe): Make sure that switching the system timer resolution |
| 153 // doesn't break Timer firing order etc. An example test would be to have |
| 154 // two threads. One would have a bunch of timers, and another would turn the |
| 155 // high resolution timer on and off. |
| 156 |
| 157 MMRESULT result; |
| 158 if (use) |
| 159 result = timeBeginPeriod(1); |
| 160 else |
| 161 result = timeEndPeriod(1); |
| 162 return (result == TIMERR_NOERROR); |
213 } | 163 } |
214 | 164 |
215 // static | 165 // static |
216 void Time::EnableHiResClockForTests() { | |
217 Singleton<HighResolutionTimerManager>()->Enable(); | |
218 } | |
219 | |
220 // static | |
221 Time Time::FromExploded(bool is_local, const Exploded& exploded) { | 166 Time Time::FromExploded(bool is_local, const Exploded& exploded) { |
222 // Create the system struct representing our exploded time. It will either be | 167 // Create the system struct representing our exploded time. It will either be |
223 // in local time or UTC. | 168 // in local time or UTC. |
224 SYSTEMTIME st; | 169 SYSTEMTIME st; |
225 st.wYear = exploded.year; | 170 st.wYear = exploded.year; |
226 st.wMonth = exploded.month; | 171 st.wMonth = exploded.month; |
227 st.wDayOfWeek = exploded.day_of_week; | 172 st.wDayOfWeek = exploded.day_of_week; |
228 st.wDay = exploded.day_of_month; | 173 st.wDay = exploded.day_of_month; |
229 st.wHour = exploded.hour; | 174 st.wHour = exploded.hour; |
230 st.wMinute = exploded.minute; | 175 st.wMinute = exploded.minute; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 | 381 |
437 // static | 382 // static |
438 TimeTicks TimeTicks::Now() { | 383 TimeTicks TimeTicks::Now() { |
439 return TimeTicks() + Singleton<NowSingleton>::get()->Now(); | 384 return TimeTicks() + Singleton<NowSingleton>::get()->Now(); |
440 } | 385 } |
441 | 386 |
442 // static | 387 // static |
443 TimeTicks TimeTicks::HighResNow() { | 388 TimeTicks TimeTicks::HighResNow() { |
444 return TimeTicks() + Singleton<HighResNowSingleton>::get()->Now(); | 389 return TimeTicks() + Singleton<HighResNowSingleton>::get()->Now(); |
445 } | 390 } |
OLD | NEW |