diff options
-rw-r--r-- | base/test_suite.h | 10 | ||||
-rw-r--r-- | base/time.h | 7 | ||||
-rw-r--r-- | base/time_win.cc | 105 | ||||
-rw-r--r-- | chrome/browser/browser_main.cc | 5 |
4 files changed, 95 insertions, 32 deletions
diff --git a/base/test_suite.h b/base/test_suite.h index 79fe5cf..584b945 100644 --- a/base/test_suite.h +++ b/base/test_suite.h @@ -18,6 +18,7 @@ #include "base/logging.h" #include "base/multiprocess_test.h" #include "base/scoped_nsautorelease_pool.h" +#include "base/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" @@ -108,6 +109,11 @@ class TestSuite { logging::SetLogItems(true, true, true, true); #if defined(OS_WIN) + // For unit tests we turn on the high resolution timer and disable + // base::Time's use of SystemMonitor. Tests create and destroy the message + // loop, which causes a crash with SystemMonitor (http://crbug.com/12187). + base::Time::EnableHiResClockForTests(); + // In some cases, we do not want to see standard error dialogs. if (!IsDebuggerPresent() && !CommandLine::ForCurrentProcess()->HasSwitch(L"show-error-dialogs")) { @@ -116,9 +122,9 @@ class TestSuite { // When the code in this file moved around, bug 6436 resurfaced. // As a hack workaround, just #ifdef out this code for Purify builds. logging::SetLogAssertHandler(UnitTestAssertHandler); -#endif +#endif // !defined(PURIFY) } -#endif +#endif // defined(OS_WIN) icu_util::Initialize(); } diff --git a/base/time.h b/base/time.h index 0625bfb..beeca27 100644 --- a/base/time.h +++ b/base/time.h @@ -228,6 +228,13 @@ class Time { #if defined(OS_WIN) static Time FromFileTime(FILETIME ft); FILETIME ToFileTime() const; + + // Monitor system power state and disable high resolution timer when we're + // on battery. See time_win.cc for more details. + static void StartSystemMonitorObserver(); + + // Enable high resolution timer unconditionally. Only for test code. + static void EnableHiResClockForTests(); #endif // Converts an exploded structure representing either the local time or UTC diff --git a/base/time_win.cc b/base/time_win.cc index fa24868..d0c9702 100644 --- a/base/time_win.cc +++ b/base/time_win.cc @@ -88,6 +88,69 @@ void InitializeClock() { initial_time = CurrentWallclockMicroseconds(); } +class HighResolutionTimerManager : public base::SystemMonitor::PowerObserver { + public: + ~HighResolutionTimerManager() { + StopMonitoring(); + UseHiResClock(false); + } + + void Enable() { + StopMonitoring(); + UseHiResClock(true); + } + + void StartMonitoring() { + if (is_monitoring_) + return; + is_monitoring_ = true; + base::SystemMonitor* system = base::SystemMonitor::Get(); + DCHECK(system); + system->AddObserver(this); + UseHiResClock(!system->BatteryPower()); + } + + void StopMonitoring() { + if (!is_monitoring_) + return; + is_monitoring_ = false; + base::SystemMonitor* monitor = base::SystemMonitor::Get(); + if (monitor) + monitor->RemoveObserver(this); + } + + // Interfaces for monitoring Power changes. + void OnPowerStateChange(base::SystemMonitor* system) { + UseHiResClock(!system->BatteryPower()); + } + + void OnSuspend(base::SystemMonitor* system) {} + void OnResume(base::SystemMonitor* system) {} + + private: + HighResolutionTimerManager() + : is_monitoring_(false), + hi_res_clock_enabled_(false) { + } + friend struct DefaultSingletonTraits<HighResolutionTimerManager>; + + // Enable or disable the faster multimedia timer. + void UseHiResClock(bool enabled) { + if (enabled == hi_res_clock_enabled_) + return; + if (enabled) + timeBeginPeriod(1); + else + timeEndPeriod(1); + hi_res_clock_enabled_ = enabled; + } + + bool is_monitoring_; + bool hi_res_clock_enabled_; + + DISALLOW_COPY_AND_ASSIGN(HighResolutionTimerManager); +}; + } // namespace // Time ----------------------------------------------------------------------- @@ -149,6 +212,16 @@ FILETIME Time::ToFileTime() const { } // static +void Time::StartSystemMonitorObserver() { + Singleton<HighResolutionTimerManager>()->StartMonitoring(); +} + +// static +void Time::EnableHiResClockForTests() { + Singleton<HighResolutionTimerManager>()->Enable(); +} + +// static Time Time::FromExploded(bool is_local, const Exploded& exploded) { // Create the system struct representing our exploded time. It will either be // in local time or UTC. @@ -227,22 +300,14 @@ DWORD (*tick_function)(void) = &timeGetTimeWrapper; // which will roll over the 32-bit value every ~49 days. We try to track // rollover ourselves, which works if TimeTicks::Now() is called at least every // 49 days. -class NowSingleton : public base::SystemMonitor::PowerObserver { +class NowSingleton { public: NowSingleton() : rollover_(TimeDelta::FromMilliseconds(0)), - last_seen_(0), - hi_res_clock_enabled_(false) { - base::SystemMonitor* system = base::SystemMonitor::Get(); - system->AddObserver(this); - UseHiResClock(!system->BatteryPower()); + last_seen_(0) { } ~NowSingleton() { - UseHiResClock(false); - base::SystemMonitor* monitor = base::SystemMonitor::Get(); - if (monitor) - monitor->RemoveObserver(this); } TimeDelta Now() { @@ -256,30 +321,10 @@ class NowSingleton : public base::SystemMonitor::PowerObserver { return TimeDelta::FromMilliseconds(now) + rollover_; } - // Interfaces for monitoring Power changes. - void OnPowerStateChange(base::SystemMonitor* system) { - UseHiResClock(!system->BatteryPower()); - } - - void OnSuspend(base::SystemMonitor* system) {} - void OnResume(base::SystemMonitor* system) {} - private: - // Enable or disable the faster multimedia timer. - void UseHiResClock(bool enabled) { - if (enabled == hi_res_clock_enabled_) - return; - if (enabled) - timeBeginPeriod(1); - else - timeEndPeriod(1); - hi_res_clock_enabled_ = enabled; - } - Lock lock_; // To protected last_seen_ and rollover_. TimeDelta rollover_; // Accumulation of time lost due to rollover. DWORD last_seen_; // The last timeGetTime value we saw, to detect rollover. - bool hi_res_clock_enabled_; DISALLOW_COPY_AND_ASSIGN(NowSingleton); }; diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index d2bc9de..5b955eb 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -265,6 +265,11 @@ int BrowserMain(const MainFunctionParams& parameters) { // Initialize the SystemMonitor base::SystemMonitor::Start(); +#if defined(OS_WIN) + // We want to monitor system power state to adjust our high resolution + // timer settings. But it's necessary only on Windows. + base::Time::StartSystemMonitorObserver(); +#endif // defined(OS_WIN) // Initialize statistical testing infrastructure. FieldTrialList field_trial; |