| Index: chrome/browser/metrics/thread_watcher.cc
|
| ===================================================================
|
| --- chrome/browser/metrics/thread_watcher.cc (revision 76170)
|
| +++ chrome/browser/metrics/thread_watcher.cc (working copy)
|
| @@ -2,14 +2,16 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#if 0
|
| -
|
| #include "base/threading/thread_restrictions.h"
|
| #include "build/build_config.h"
|
| #include "chrome/browser/metrics/metrics_service.h"
|
| #include "chrome/browser/metrics/thread_watcher.h"
|
| #include "chrome/common/notification_service.h"
|
|
|
| +#if defined(OS_WIN)
|
| +#include <Objbase.h>
|
| +#endif
|
| +
|
| // static
|
| const int ThreadWatcher::kPingCount = 3;
|
|
|
| @@ -42,19 +44,20 @@
|
| DCHECK_GE(sleep_time.InMilliseconds(), 0);
|
| DCHECK_GE(unresponsive_time.InMilliseconds(), sleep_time.InMilliseconds());
|
|
|
| - // If we are not on WATCHDOG thread, then post a task to call StartWatching on
|
| - // WATCHDOG thread.
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::WATCHDOG,
|
| - FROM_HERE,
|
| - NewRunnableFunction(
|
| - &ThreadWatcher::StartWatching,
|
| - thread_id, thread_name, sleep_time, unresponsive_time));
|
| + // If we are not on WatchDogThread, then post a task to call StartWatching on
|
| + // WatchDogThread.
|
| + if (!WatchDogThread::CurrentlyOnWatchDogThread()) {
|
| + MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
|
| + if (message_loop)
|
| + message_loop->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableFunction(
|
| + &ThreadWatcher::StartWatching,
|
| + thread_id, thread_name, sleep_time, unresponsive_time));
|
| return;
|
| }
|
|
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
|
|
| // Create a new thread watcher object for the given thread and activate it.
|
| ThreadWatcher* watcher =
|
| @@ -64,7 +67,7 @@
|
| }
|
|
|
| void ThreadWatcher::ActivateThreadWatching() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| if (active_) return;
|
| active_ = true;
|
| ping_count_ = kPingCount;
|
| @@ -74,14 +77,14 @@
|
| }
|
|
|
| void ThreadWatcher::DeActivateThreadWatching() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| active_ = false;
|
| ping_count_ = 0;
|
| method_factory_.RevokeAll();
|
| }
|
|
|
| void ThreadWatcher::WakeUp() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| // There is some user activity, PostPingMessage task of thread watcher if
|
| // needed.
|
| if (!active_) return;
|
| @@ -95,7 +98,7 @@
|
| }
|
|
|
| void ThreadWatcher::PostPingMessage() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| // If we have stopped watching or if the user is idle, then stop sending
|
| // ping messages.
|
| if (!active_ || ping_count_ <= 0)
|
| @@ -126,7 +129,7 @@
|
| }
|
|
|
| void ThreadWatcher::OnPongMessage(uint64 ping_sequence_number) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| // Record watched thread's response time.
|
| base::TimeDelta response_time = base::TimeTicks::Now() - ping_time_;
|
| histogram_->AddTime(response_time);
|
| @@ -152,7 +155,7 @@
|
| }
|
|
|
| bool ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| // If we have stopped watching then consider thread as responding.
|
| if (!active_)
|
| return true;
|
| @@ -178,7 +181,11 @@
|
| Task* callback_task) {
|
| // This method is called on watched thread.
|
| DCHECK(BrowserThread::CurrentlyOn(thread_id));
|
| - BrowserThread::PostTask(BrowserThread::WATCHDOG, FROM_HERE, callback_task);
|
| + MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
|
| + if (message_loop)
|
| + message_loop->PostTask(FROM_HERE, callback_task);
|
| + else
|
| + delete callback_task;
|
| }
|
|
|
| //------------------------------------------------------------------------------
|
| @@ -191,22 +198,15 @@
|
| : last_wakeup_time_(base::TimeTicks::Now()) {
|
| // Assert we are not running on WATCHDOG thread. Would be ideal to assert we
|
| // are on UI thread, but Unit tests are not running on UI thread.
|
| - DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| - DCHECK(!global_);
|
| + DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread());
|
| + CHECK(!global_);
|
| global_ = this;
|
| // Register Notifications observer.
|
| -#if defined(OS_WIN)
|
| MetricsService::SetupNotifications(®istrar_, this);
|
| -#endif
|
| }
|
|
|
| ThreadWatcherList::~ThreadWatcherList() {
|
| base::AutoLock auto_lock(lock_);
|
| - while (!registered_.empty()) {
|
| - RegistrationList::iterator it = registered_.begin();
|
| - delete it->second;
|
| - registered_.erase(it->first);
|
| - }
|
| DCHECK(this == global_);
|
| global_ = NULL;
|
| }
|
| @@ -224,15 +224,16 @@
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| if (!global_)
|
| return;
|
| - base::AutoLock auto_lock(global_->lock_);
|
| - for (RegistrationList::iterator it = global_->registered_.begin();
|
| - global_->registered_.end() != it;
|
| - ++it)
|
| - BrowserThread::PostTask(
|
| - BrowserThread::WATCHDOG,
|
| +
|
| + // Remove all notifications for all watched threads.
|
| + RemoveNotifications();
|
| +
|
| + // Delete all thread watcher objects on WatchDogThread.
|
| + MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
|
| + if (message_loop)
|
| + message_loop->PostTask(
|
| FROM_HERE,
|
| - NewRunnableMethod(
|
| - it->second, &ThreadWatcher::DeActivateThreadWatching));
|
| + NewRunnableMethod(global_, &ThreadWatcherList::DeleteAll));
|
| }
|
|
|
| // static
|
| @@ -240,12 +241,20 @@
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| if (!global_)
|
| return;
|
| -#if defined(OS_WIN)
|
| base::AutoLock auto_lock(global_->lock_);
|
| global_->registrar_.RemoveAll();
|
| -#endif
|
| }
|
|
|
| +void ThreadWatcherList::DeleteAll() {
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| + base::AutoLock auto_lock(lock_);
|
| + while (!registered_.empty()) {
|
| + RegistrationList::iterator it = registered_.begin();
|
| + delete it->second;
|
| + registered_.erase(it->first);
|
| + }
|
| +}
|
| +
|
| void ThreadWatcherList::Observe(NotificationType type,
|
| const NotificationSource& source,
|
| const NotificationDetails& details) {
|
| @@ -260,15 +269,17 @@
|
| last_wakeup_time_ = now;
|
| }
|
| }
|
| - if (need_to_awaken)
|
| - BrowserThread::PostTask(
|
| - BrowserThread::WATCHDOG,
|
| - FROM_HERE,
|
| - NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll));
|
| + if (need_to_awaken) {
|
| + MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop();
|
| + if (message_loop)
|
| + message_loop->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll));
|
| + }
|
| }
|
|
|
| void ThreadWatcherList::WakeUpAll() {
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG));
|
| + DCHECK(WatchDogThread::CurrentlyOnWatchDogThread());
|
| base::AutoLock auto_lock(lock_);
|
| for (RegistrationList::iterator it = global_->registered_.begin();
|
| global_->registered_.end() != it;
|
| @@ -294,42 +305,81 @@
|
| //------------------------------------------------------------------------------
|
| // WatchDogThread methods and members.
|
|
|
| +// static
|
| +base::Lock WatchDogThread::lock_;
|
| +// static
|
| +WatchDogThread* WatchDogThread::watchdog_thread_ = NULL;
|
| +
|
| // The WatchDogThread object must outlive any tasks posted to the IO thread
|
| // before the Quit task.
|
| DISABLE_RUNNABLE_METHOD_REFCOUNT(WatchDogThread);
|
|
|
| -WatchDogThread::WatchDogThread()
|
| - : BrowserProcessSubThread(BrowserThread::WATCHDOG) {
|
| +WatchDogThread::WatchDogThread() : Thread("WATCHDOG") {
|
| }
|
|
|
| WatchDogThread::~WatchDogThread() {
|
| - // Remove all notifications for all watched threads.
|
| - ThreadWatcherList::RemoveNotifications();
|
| // We cannot rely on our base class to stop the thread since we want our
|
| // CleanUp function to run.
|
| Stop();
|
| }
|
|
|
| +void WatchDogThread::StartWatchingAll() {
|
| + const base::TimeDelta kSleepTime = base::TimeDelta::FromSeconds(5);
|
| + const base::TimeDelta kUnresponsiveTime = base::TimeDelta::FromSeconds(10);
|
| + if (BrowserThread::IsMessageLoopValid(BrowserThread::UI))
|
| + ThreadWatcher::StartWatching(BrowserThread::UI, "UI", kSleepTime,
|
| + kUnresponsiveTime);
|
| + if (BrowserThread::IsMessageLoopValid(BrowserThread::IO))
|
| + ThreadWatcher::StartWatching(BrowserThread::IO, "IO", kSleepTime,
|
| + kUnresponsiveTime);
|
| + if (BrowserThread::IsMessageLoopValid(BrowserThread::DB))
|
| + ThreadWatcher::StartWatching(BrowserThread::DB, "DB", kSleepTime,
|
| + kUnresponsiveTime);
|
| + if (BrowserThread::IsMessageLoopValid(BrowserThread::FILE))
|
| + ThreadWatcher::StartWatching(BrowserThread::FILE, "FILE", kSleepTime,
|
| + kUnresponsiveTime);
|
| + if (BrowserThread::IsMessageLoopValid(BrowserThread::CACHE))
|
| + ThreadWatcher::StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime,
|
| + kUnresponsiveTime);
|
| +}
|
| +
|
| +// static
|
| +MessageLoop* WatchDogThread::CurrentMessageLoop() {
|
| + base::AutoLock lock(lock_);
|
| + MessageLoop* message_loop = watchdog_thread_ ?
|
| + watchdog_thread_->message_loop() : NULL;
|
| + return message_loop;
|
| +}
|
| +
|
| +// static
|
| +bool WatchDogThread::CurrentlyOnWatchDogThread() {
|
| + base::AutoLock lock(lock_);
|
| + return watchdog_thread_ &&
|
| + watchdog_thread_->message_loop() == MessageLoop::current();
|
| +}
|
| +
|
| void WatchDogThread::Init() {
|
| // This thread shouldn't be allowed to perform any blocking disk I/O.
|
| base::ThreadRestrictions::SetIOAllowed(false);
|
|
|
| - BrowserProcessSubThread::Init();
|
| +#if defined(OS_WIN)
|
| + // Initializes the COM library on the current thread.
|
| + CoInitialize(NULL);
|
| +#endif
|
|
|
| + base::AutoLock lock(lock_);
|
| + watchdog_thread_ = this;
|
| +}
|
| +
|
| +void WatchDogThread::CleanUp() {
|
| + base::AutoLock lock(lock_);
|
| + watchdog_thread_ = NULL;
|
| +}
|
| +
|
| +void WatchDogThread::CleanUpAfterMessageLoopDestruction() {
|
| #if defined(OS_WIN)
|
| - const base::TimeDelta kSleepTime = base::TimeDelta::FromSeconds(5);
|
| - const base::TimeDelta kUnresponsiveTime = base::TimeDelta::FromSeconds(10);
|
| - ThreadWatcher::StartWatching(BrowserThread::UI, "UI", kSleepTime,
|
| - kUnresponsiveTime);
|
| - ThreadWatcher::StartWatching(BrowserThread::IO, "IO", kSleepTime,
|
| - kUnresponsiveTime);
|
| - ThreadWatcher::StartWatching(BrowserThread::DB, "DB", kSleepTime,
|
| - kUnresponsiveTime);
|
| - ThreadWatcher::StartWatching(BrowserThread::FILE, "FILE", kSleepTime,
|
| - kUnresponsiveTime);
|
| - ThreadWatcher::StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime,
|
| - kUnresponsiveTime);
|
| + // Closes the COM library on the current thread. CoInitialize must
|
| + // be balanced by a corresponding call to CoUninitialize.
|
| + CoUninitialize();
|
| #endif
|
| }
|
| -
|
| -#endif // 0
|
|
|