| Index: base/time/time_win.cc
|
| diff --git a/base/time/time_win.cc b/base/time/time_win.cc
|
| index 5fa899d1f97f69be69d1df65ba854565d7240b53..492b54a93f126717ad0b2c339e75322bdeeb1532 100644
|
| --- a/base/time/time_win.cc
|
| +++ b/base/time/time_win.cc
|
| @@ -29,10 +29,7 @@
|
| //
|
| // To work around all this, we're going to generally use timeGetTime(). We
|
| // will only increase the system-wide timer if we're not running on battery
|
| -// power. Using timeBeginPeriod(1) is a requirement in order to make our
|
| -// message loop waits have the same resolution that our time measurements
|
| -// do. Otherwise, WaitForSingleObject(..., 1) will no less than 15ms when
|
| -// there is nothing else to waken the Wait.
|
| +// power.
|
|
|
| #include "base/time/time.h"
|
|
|
| @@ -87,6 +84,19 @@ void InitializeClock() {
|
| initial_time = CurrentWallclockMicroseconds();
|
| }
|
|
|
| +// The two values that ActivateHighResolutionTimer uses to set the systemwide
|
| +// timer interrupt frequency on Windows. It controls how precise timers are
|
| +// but also has a big impact on battery life.
|
| +const int kMinTimerIntervalHighResMs = 1;
|
| +const int kMinTimerIntervalLowResMs = 4;
|
| +// Track if kMinTimerIntervalHighResMs or kMinTimerIntervalLowResMs is active.
|
| +bool g_high_res_timer_enabled = false;
|
| +// How many times the high resolution timer has been called.
|
| +int g_high_res_timer_count = 0;
|
| +// The lock to control access to the above two variables.
|
| +base::LazyInstance<base::Lock>::Leaky g_high_res_lock =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| } // namespace
|
|
|
| // Time -----------------------------------------------------------------------
|
| @@ -98,9 +108,6 @@ void InitializeClock() {
|
| // static
|
| const int64 Time::kTimeTToMicrosecondsOffset = GG_INT64_C(11644473600000000);
|
|
|
| -bool Time::high_resolution_timer_enabled_ = false;
|
| -int Time::high_resolution_timer_activated_ = 0;
|
| -
|
| // static
|
| Time Time::Now() {
|
| if (initial_time == 0)
|
| @@ -165,44 +172,51 @@ FILETIME Time::ToFileTime() const {
|
|
|
| // static
|
| void Time::EnableHighResolutionTimer(bool enable) {
|
| - // Test for single-threaded access.
|
| - static PlatformThreadId my_thread = PlatformThread::CurrentId();
|
| - DCHECK(PlatformThread::CurrentId() == my_thread);
|
| -
|
| - if (high_resolution_timer_enabled_ == enable)
|
| + base::AutoLock lock(g_high_res_lock.Get());
|
| + if (g_high_res_timer_enabled == enable)
|
| return;
|
| -
|
| - high_resolution_timer_enabled_ = enable;
|
| + g_high_res_timer_enabled = enable;
|
| + if (!g_high_res_timer_count)
|
| + return;
|
| + // Since g_high_res_timer_count != 0, an ActivateHighResolutionTimer(true)
|
| + // was called which called timeBeginPeriod with g_high_res_timer_enabled
|
| + // with a value which is the opposite of |enable|. With that information we
|
| + // call timeEndPeriod with the same value used in timeBeginPeriod and
|
| + // therefore undo the period effect.
|
| + if (enable) {
|
| + timeEndPeriod(kMinTimerIntervalLowResMs);
|
| + timeBeginPeriod(kMinTimerIntervalHighResMs);
|
| + } else {
|
| + timeEndPeriod(kMinTimerIntervalHighResMs);
|
| + timeBeginPeriod(kMinTimerIntervalLowResMs);
|
| + }
|
| }
|
|
|
| // static
|
| bool Time::ActivateHighResolutionTimer(bool activating) {
|
| - if (!high_resolution_timer_enabled_ && activating)
|
| - return false;
|
| + // We only do work on the transition from zero to one or one to zero so we
|
| + // can easily undo the effect (if necessary) when EnableHighResolutionTimer is
|
| + // called.
|
| + base::AutoLock lock(g_high_res_lock.Get());
|
| + UINT period = g_high_res_timer_enabled ? kMinTimerIntervalHighResMs
|
| + : kMinTimerIntervalLowResMs;
|
| + int high_res_count =
|
| + activating ? ++g_high_res_timer_count : --g_high_res_timer_count;
|
|
|
| - // Using anything other than 1ms makes timers granular
|
| - // to that interval.
|
| - const int kMinTimerIntervalMs = 1;
|
| - MMRESULT result;
|
| if (activating) {
|
| - result = timeBeginPeriod(kMinTimerIntervalMs);
|
| - high_resolution_timer_activated_++;
|
| + if (high_res_count == 1)
|
| + timeBeginPeriod(period);
|
| } else {
|
| - result = timeEndPeriod(kMinTimerIntervalMs);
|
| - high_resolution_timer_activated_--;
|
| + if (high_res_count == 0)
|
| + timeEndPeriod(period);
|
| }
|
| - return result == TIMERR_NOERROR;
|
| + return (period == kMinTimerIntervalHighResMs);
|
| }
|
|
|
| // static
|
| bool Time::IsHighResolutionTimerInUse() {
|
| - // Note: we should track the high_resolution_timer_activated_ value
|
| - // under a lock if we want it to be accurate in a system with multiple
|
| - // message loops. We don't do that - because we don't want to take the
|
| - // expense of a lock for this. We *only* track this value so that unit
|
| - // tests can see if the high resolution timer is on or off.
|
| - return high_resolution_timer_enabled_ &&
|
| - high_resolution_timer_activated_ > 0;
|
| + base::AutoLock lock(g_high_res_lock.Get());
|
| + return g_high_res_timer_enabled && g_high_res_timer_count > 0;
|
| }
|
|
|
| // static
|
|
|