summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-26 19:48:34 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-26 19:48:34 +0000
commit097ae5a93a863b604fd6dbd939bed0c2be1afed2 (patch)
tree61177362b1c1bd2d1b2438acc50ccb2c061b176e /base
parent902c971382790170852fe5b5d22d1b79adb31056 (diff)
downloadchromium_src-097ae5a93a863b604fd6dbd939bed0c2be1afed2.zip
chromium_src-097ae5a93a863b604fd6dbd939bed0c2be1afed2.tar.gz
chromium_src-097ae5a93a863b604fd6dbd939bed0c2be1afed2.tar.bz2
Make SystemMonitor not a Singleton and move it out of base
SystemMonitor makes an assumption that through its lifetime a MessageLoop exists and stays the same. It is difficult and error-prone to satisfy that when it is a Singleton. It has caused problems in the past. Additionally, extract HighResoltionTimerManager out of time_win.cc, eliminating yet another Singleton. TEST=none BUG=none Review URL: http://codereview.chromium.org/431008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33214 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/base.gyp5
-rw-r--r--base/system_monitor.cc98
-rw-r--r--base/system_monitor.h129
-rw-r--r--base/system_monitor_posix.cc14
-rw-r--r--base/system_monitor_unittest.cc86
-rw-r--r--base/system_monitor_win.cc52
-rw-r--r--base/test/test_suite.h8
-rw-r--r--base/time.h9
-rw-r--r--base/time_win.cc79
9 files changed, 19 insertions, 461 deletions
diff --git a/base/base.gyp b/base/base.gyp
index 7238928..23b85b1 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -321,10 +321,6 @@
'sys_string_conversions_linux.cc',
'sys_string_conversions_mac.mm',
'sys_string_conversions_win.cc',
- 'system_monitor.cc',
- 'system_monitor.h',
- 'system_monitor_posix.cc',
- 'system_monitor_win.cc',
'task.h',
'thread.cc',
'thread.h',
@@ -654,7 +650,6 @@
'sys_info_unittest.cc',
'sys_string_conversions_mac_unittest.mm',
'sys_string_conversions_unittest.cc',
- 'system_monitor_unittest.cc',
'task_unittest.cc',
'thread_collision_warner_unittest.cc',
'thread_local_storage_unittest.cc',
diff --git a/base/system_monitor.cc b/base/system_monitor.cc
deleted file mode 100644
index 44cdce5..0000000
--- a/base/system_monitor.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/system_monitor.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/singleton.h"
-
-namespace base {
-
-#if defined(ENABLE_BATTERY_MONITORING)
-// The amount of time (in ms) to wait before running the initial
-// battery check.
-static int kDelayedBatteryCheckMs = 10 * 1000;
-#endif // defined(ENABLE_BATTERY_MONITORING)
-
-SystemMonitor::SystemMonitor()
- : battery_in_use_(false),
- suspended_(false) {
- observer_list_ = new ObserverListThreadSafe<PowerObserver>();
-}
-
-void SystemMonitor::ProcessPowerMessage(PowerEvent event_id) {
- // Suppress duplicate notifications. Some platforms may
- // send multiple notifications of the same event.
- switch (event_id) {
- case POWER_STATE_EVENT:
- {
- bool on_battery = IsBatteryPower();
- if (on_battery != battery_in_use_) {
- battery_in_use_ = on_battery;
- NotifyPowerStateChange();
- }
- }
- break;
- case RESUME_EVENT:
- if (suspended_) {
- suspended_ = false;
- NotifyResume();
- }
- break;
- case SUSPEND_EVENT:
- if (!suspended_) {
- suspended_ = true;
- NotifySuspend();
- }
- break;
- }
-}
-
-void SystemMonitor::AddObserver(PowerObserver* obs) {
- observer_list_->AddObserver(obs);
-}
-
-void SystemMonitor::RemoveObserver(PowerObserver* obs) {
- observer_list_->RemoveObserver(obs);
-}
-
-void SystemMonitor::NotifyPowerStateChange() {
- LOG(INFO) << L"PowerStateChange: "
- << (BatteryPower() ? L"On" : L"Off") << L" battery";
- observer_list_->Notify(&PowerObserver::OnPowerStateChange, BatteryPower());
-}
-
-void SystemMonitor::NotifySuspend() {
- LOG(INFO) << L"Power Suspending";
- observer_list_->Notify(&PowerObserver::OnSuspend);
-}
-
-void SystemMonitor::NotifyResume() {
- LOG(INFO) << L"Power Resuming";
- observer_list_->Notify(&PowerObserver::OnResume);
-}
-
-// static
-SystemMonitor* SystemMonitor::Get() {
- // Uses the LeakySingletonTrait because cleanup is optional.
- return
- Singleton<SystemMonitor, LeakySingletonTraits<SystemMonitor> >::get();
-}
-
-// static
-void SystemMonitor::Start() {
-#if defined(ENABLE_BATTERY_MONITORING)
- DCHECK(MessageLoop::current()); // Can't call start too early.
- SystemMonitor* monitor = Get();
- monitor->delayed_battery_check_.Start(
- TimeDelta::FromMilliseconds(kDelayedBatteryCheckMs), monitor,
- &SystemMonitor::BatteryCheck);
-#endif // defined(ENABLE_BATTERY_MONITORING)
-}
-
-void SystemMonitor::BatteryCheck() {
- ProcessPowerMessage(SystemMonitor::POWER_STATE_EVENT);
-}
-
-} // namespace base
diff --git a/base/system_monitor.h b/base/system_monitor.h
deleted file mode 100644
index 71d8436..0000000
--- a/base/system_monitor.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_SYSTEM_MONITOR_H_
-#define BASE_SYSTEM_MONITOR_H_
-
-#include "build/build_config.h"
-
-// Windows HiRes timers drain the battery faster so we need to know the battery
-// status. This isn't true for other platforms.
-#if defined(OS_WIN)
-#define ENABLE_BATTERY_MONITORING 1
-#else
-#undef ENABLE_BATTERY_MONITORING
-#endif // !OS_WIN
-
-#include "base/observer_list_threadsafe.h"
-#if defined(ENABLE_BATTERY_MONITORING)
-#include "base/timer.h"
-#endif // defined(ENABLE_BATTERY_MONITORING)
-
-namespace base {
-
-// Class for monitoring various system-related subsystems
-// such as power management, network status, etc.
-// TODO(mbelshe): Add support beyond just power management.
-class SystemMonitor {
- public:
- // Retrieves the Singleton.
- static SystemMonitor* Get();
-
- // Start the System Monitor within a process. This method
- // is provided so that the battery check can be deferred.
- // The MessageLoop must be started before calling this
- // method.
- // This is a no-op on platforms for which ENABLE_BATTERY_MONITORING is
- // disabled.
- static void Start();
-
- //
- // Power-related APIs
- //
-
- // Is the computer currently on battery power.
- // Can be called on any thread.
- bool BatteryPower() const {
- // Using a lock here is not necessary for just a bool.
- return battery_in_use_;
- }
-
- // Normalized list of power events.
- enum PowerEvent {
- POWER_STATE_EVENT, // The Power status of the system has changed.
- SUSPEND_EVENT, // The system is being suspended.
- RESUME_EVENT // The system is being resumed.
- };
-
- // Callbacks will be called on the thread which creates the SystemMonitor.
- // During the callback, Add/RemoveObserver will block until the callbacks
- // are finished. Observers should implement quick callback functions; if
- // lengthy operations are needed, the observer should take care to invoke
- // the operation on an appropriate thread.
- class PowerObserver {
- public:
- // Notification of a change in power status of the computer, such
- // as from switching between battery and A/C power.
- virtual void OnPowerStateChange(bool on_battery_power) {}
-
- // Notification that the system is suspending.
- virtual void OnSuspend() {}
-
- // Notification that the system is resuming.
- virtual void OnResume() {}
- };
-
- // Add a new observer.
- // Can be called from any thread.
- // Must not be called from within a notification callback.
- void AddObserver(PowerObserver* obs);
-
- // Remove an existing observer.
- // Can be called from any thread.
- // Must not be called from within a notification callback.
- void RemoveObserver(PowerObserver* obs);
-
-#if defined(OS_WIN)
- // Windows-specific handling of a WM_POWERBROADCAST message.
- // Embedders of this API should hook their top-level window
- // message loop and forward WM_POWERBROADCAST through this call.
- void ProcessWmPowerBroadcastMessage(int event_id);
-#endif
-
- // Cross-platform handling of a power event.
- void ProcessPowerMessage(PowerEvent event_id);
-
- // Constructor.
- // Don't use this; access SystemMonitor via the Singleton.
- SystemMonitor();
-
- private:
- // Platform-specific method to check whether the system is currently
- // running on battery power. Returns true if running on batteries,
- // false otherwise.
- bool IsBatteryPower();
-
- // Checks the battery status and notifies observers if the battery
- // status has changed.
- void BatteryCheck();
-
- // Functions to trigger notifications.
- void NotifyPowerStateChange();
- void NotifySuspend();
- void NotifyResume();
-
- scoped_refptr<ObserverListThreadSafe<PowerObserver> > observer_list_;
- bool battery_in_use_;
- bool suspended_;
-
-#if defined(ENABLE_BATTERY_MONITORING)
- base::OneShotTimer<SystemMonitor> delayed_battery_check_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(SystemMonitor);
-};
-
-}
-
-#endif // BASE_SYSTEM_MONITOR_H_
diff --git a/base/system_monitor_posix.cc b/base/system_monitor_posix.cc
deleted file mode 100644
index a4a118c..0000000
--- a/base/system_monitor_posix.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/system_monitor.h"
-
-namespace base {
-
-bool SystemMonitor::IsBatteryPower() {
- NOTIMPLEMENTED();
- return false;
-}
-
-} // namespace base
diff --git a/base/system_monitor_unittest.cc b/base/system_monitor_unittest.cc
deleted file mode 100644
index 7ba3a6b..0000000
--- a/base/system_monitor_unittest.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/system_monitor.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-class PowerTest : public base::SystemMonitor::PowerObserver {
- public:
- PowerTest()
- : battery_(false),
- power_state_changes_(0),
- suspends_(0),
- resumes_(0) {};
-
- // PowerObserver callbacks.
- void OnPowerStateChange(bool on_battery_power) {
- power_state_changes_++;
- }
-
- void OnSuspend() {
- suspends_++;
- }
-
- void OnResume() {
- resumes_++;
- }
-
- // Test status counts.
- bool battery() { return battery_; }
- int power_state_changes() { return power_state_changes_; }
- int suspends() { return suspends_; }
- int resumes() { return resumes_; }
-
- private:
- bool battery_; // Do we currently think we're on battery power.
- int power_state_changes_; // Count of OnPowerStateChange notifications.
- int suspends_; // Count of OnSuspend notifications.
- int resumes_; // Count of OnResume notifications.
-};
-
-TEST(SystemMonitor, PowerNotifications) {
- const int kObservers = 5;
-
- // Initialize a message loop for this to run on.
- MessageLoop loop;
- // Initialize time() since it registers as a SystemMonitor observer.
- base::Time now = base::Time::Now();
-
- base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
- PowerTest test[kObservers];
- for (int index = 0; index < kObservers; ++index)
- system_monitor->AddObserver(&test[index]);
-
- // Send a bunch of power changes. Since the battery power hasn't
- // actually changed, we shouldn't get notifications.
- for (int index = 0; index < 5; index++) {
- system_monitor->ProcessPowerMessage(base::SystemMonitor::POWER_STATE_EVENT);
- EXPECT_EQ(test[0].power_state_changes(), 0);
- }
-
- // Sending resume when not suspended should have no effect.
- system_monitor->ProcessPowerMessage(base::SystemMonitor::RESUME_EVENT);
- loop.RunAllPending();
- EXPECT_EQ(test[0].resumes(), 0);
-
- // Pretend we suspended.
- system_monitor->ProcessPowerMessage(base::SystemMonitor::SUSPEND_EVENT);
- loop.RunAllPending();
- EXPECT_EQ(test[0].suspends(), 1);
-
- // Send a second suspend notification. This should be suppressed.
- system_monitor->ProcessPowerMessage(base::SystemMonitor::SUSPEND_EVENT);
- loop.RunAllPending();
- EXPECT_EQ(test[0].suspends(), 1);
-
- // Pretend we were awakened.
- system_monitor->ProcessPowerMessage(base::SystemMonitor::RESUME_EVENT);
- loop.RunAllPending();
- EXPECT_EQ(test[0].resumes(), 1);
-
- // Send a duplicate resume notification. This should be suppressed.
- system_monitor->ProcessPowerMessage(base::SystemMonitor::RESUME_EVENT);
- loop.RunAllPending();
- EXPECT_EQ(test[0].resumes(), 1);
-}
diff --git a/base/system_monitor_win.cc b/base/system_monitor_win.cc
deleted file mode 100644
index 8a2d8c9..0000000
--- a/base/system_monitor_win.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2008 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/system_monitor.h"
-
-namespace base {
-
-void SystemMonitor::ProcessWmPowerBroadcastMessage(int event_id) {
- PowerEvent power_event;
- switch (event_id) {
- case PBT_APMPOWERSTATUSCHANGE: // The power status changed.
- power_event = POWER_STATE_EVENT;
- break;
- case PBT_APMRESUMEAUTOMATIC: // Resume from suspend.
- //case PBT_APMRESUMESUSPEND: // User-initiated resume from suspend.
- // We don't notify for this latter event
- // because if it occurs it is always sent as a
- // second event after PBT_APMRESUMEAUTOMATIC.
- power_event = RESUME_EVENT;
- break;
- case PBT_APMSUSPEND: // System has been suspended.
- power_event = SUSPEND_EVENT;
- break;
- default:
- return;
-
- // Other Power Events:
- // PBT_APMBATTERYLOW - removed in Vista.
- // PBT_APMOEMEVENT - removed in Vista.
- // PBT_APMQUERYSUSPEND - removed in Vista.
- // PBT_APMQUERYSUSPENDFAILED - removed in Vista.
- // PBT_APMRESUMECRITICAL - removed in Vista.
- // PBT_POWERSETTINGCHANGE - user changed the power settings.
- }
- ProcessPowerMessage(power_event);
-}
-
-// Function to query the system to see if it is currently running on
-// battery power. Returns true if running on battery.
-bool SystemMonitor::IsBatteryPower() {
- SYSTEM_POWER_STATUS status;
- if (!GetSystemPowerStatus(&status)) {
- LOG(ERROR) << "GetSystemPowerStatus failed: " << GetLastError();
- return false;
- }
- return (status.ACLineStatus == 0);
-}
-
-
-
-} // namespace base
diff --git a/base/test/test_suite.h b/base/test/test_suite.h
index 44e8511..2566b1a 100644
--- a/base/test/test_suite.h
+++ b/base/test/test_suite.h
@@ -182,10 +182,10 @@ class TestSuite {
CHECK(base::EnableInProcessStackDumping());
#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();
+ // Make sure we run with high resolution timer to minimize differences
+ // between production code and test code.
+ bool result = base::Time::UseHighResolutionTimer(true);
+ CHECK(result);
// In some cases, we do not want to see standard error dialogs.
if (!IsDebuggerPresent() &&
diff --git a/base/time.h b/base/time.h
index 8cd752a..33ab227 100644
--- a/base/time.h
+++ b/base/time.h
@@ -242,12 +242,9 @@ class Time {
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();
+ // Enable or disable Windows high resolution timer. For more details
+ // see comments in time_win.cc. Returns true on success.
+ static bool UseHighResolutionTimer(bool use);
#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 9fdcab1..eedf468 100644
--- a/base/time_win.cc
+++ b/base/time_win.cc
@@ -45,7 +45,6 @@
#include "base/logging.h"
#include "base/cpu.h"
#include "base/singleton.h"
-#include "base/system_monitor.h"
using base::Time;
using base::TimeDelta;
@@ -88,65 +87,6 @@ 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_monitor = base::SystemMonitor::Get();
- system_monitor->AddObserver(this);
- UseHiResClock(!system_monitor->BatteryPower());
- }
-
- void StopMonitoring() {
- if (!is_monitoring_)
- return;
- is_monitoring_ = false;
- base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
- if (system_monitor)
- system_monitor->RemoveObserver(this);
- }
-
- // Interfaces for monitoring Power changes.
- void OnPowerStateChange(bool on_battery_power) {
- UseHiResClock(!on_battery_power);
- }
-
- 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 -----------------------------------------------------------------------
@@ -208,13 +148,18 @@ FILETIME Time::ToFileTime() const {
}
// static
-void Time::StartSystemMonitorObserver() {
- Singleton<HighResolutionTimerManager>()->StartMonitoring();
-}
-
-// static
-void Time::EnableHiResClockForTests() {
- Singleton<HighResolutionTimerManager>()->Enable();
+bool Time::UseHighResolutionTimer(bool use) {
+ // TODO(mbelshe): Make sure that switching the system timer resolution
+ // doesn't break Timer firing order etc. An example test would be to have
+ // two threads. One would have a bunch of timers, and another would turn the
+ // high resolution timer on and off.
+
+ MMRESULT result;
+ if (use)
+ result = timeBeginPeriod(1);
+ else
+ result = timeEndPeriod(1);
+ return (result == TIMERR_NOERROR);
}
// static