| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #if 0 | |
| 6 | |
| 7 #include "base/threading/thread_restrictions.h" | 5 #include "base/threading/thread_restrictions.h" |
| 8 #include "build/build_config.h" | 6 #include "build/build_config.h" |
| 9 #include "chrome/browser/metrics/metrics_service.h" | 7 #include "chrome/browser/metrics/metrics_service.h" |
| 10 #include "chrome/browser/metrics/thread_watcher.h" | 8 #include "chrome/browser/metrics/thread_watcher.h" |
| 11 #include "chrome/common/notification_service.h" | 9 #include "chrome/common/notification_service.h" |
| 12 | 10 |
| 11 #if defined(OS_WIN) |
| 12 #include <Objbase.h> |
| 13 #endif |
| 14 |
| 13 // static | 15 // static |
| 14 const int ThreadWatcher::kPingCount = 3; | 16 const int ThreadWatcher::kPingCount = 3; |
| 15 | 17 |
| 16 //------------------------------------------------------------------------------ | 18 //------------------------------------------------------------------------------ |
| 17 // ThreadWatcher methods and members. | 19 // ThreadWatcher methods and members. |
| 18 | 20 |
| 19 ThreadWatcher::ThreadWatcher(const BrowserThread::ID thread_id, | 21 ThreadWatcher::ThreadWatcher(const BrowserThread::ID thread_id, |
| 20 const std::string& thread_name, | 22 const std::string& thread_name, |
| 21 const base::TimeDelta& sleep_time, | 23 const base::TimeDelta& sleep_time, |
| 22 const base::TimeDelta& unresponsive_time) | 24 const base::TimeDelta& unresponsive_time) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 35 ThreadWatcher::~ThreadWatcher() {} | 37 ThreadWatcher::~ThreadWatcher() {} |
| 36 | 38 |
| 37 // static | 39 // static |
| 38 void ThreadWatcher::StartWatching(const BrowserThread::ID thread_id, | 40 void ThreadWatcher::StartWatching(const BrowserThread::ID thread_id, |
| 39 const std::string& thread_name, | 41 const std::string& thread_name, |
| 40 const base::TimeDelta& sleep_time, | 42 const base::TimeDelta& sleep_time, |
| 41 const base::TimeDelta& unresponsive_time) { | 43 const base::TimeDelta& unresponsive_time) { |
| 42 DCHECK_GE(sleep_time.InMilliseconds(), 0); | 44 DCHECK_GE(sleep_time.InMilliseconds(), 0); |
| 43 DCHECK_GE(unresponsive_time.InMilliseconds(), sleep_time.InMilliseconds()); | 45 DCHECK_GE(unresponsive_time.InMilliseconds(), sleep_time.InMilliseconds()); |
| 44 | 46 |
| 45 // If we are not on WATCHDOG thread, then post a task to call StartWatching on | 47 // If we are not on WatchDogThread, then post a task to call StartWatching on |
| 46 // WATCHDOG thread. | 48 // WatchDogThread. |
| 47 if (!BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)) { | 49 if (!WatchDogThread::CurrentlyOnWatchDogThread()) { |
| 48 BrowserThread::PostTask( | 50 MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop(); |
| 49 BrowserThread::WATCHDOG, | 51 if (message_loop) |
| 50 FROM_HERE, | 52 message_loop->PostTask( |
| 51 NewRunnableFunction( | 53 FROM_HERE, |
| 52 &ThreadWatcher::StartWatching, | 54 NewRunnableFunction( |
| 53 thread_id, thread_name, sleep_time, unresponsive_time)); | 55 &ThreadWatcher::StartWatching, |
| 56 thread_id, thread_name, sleep_time, unresponsive_time)); |
| 54 return; | 57 return; |
| 55 } | 58 } |
| 56 | 59 |
| 57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 60 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 58 | 61 |
| 59 // Create a new thread watcher object for the given thread and activate it. | 62 // Create a new thread watcher object for the given thread and activate it. |
| 60 ThreadWatcher* watcher = | 63 ThreadWatcher* watcher = |
| 61 new ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time); | 64 new ThreadWatcher(thread_id, thread_name, sleep_time, unresponsive_time); |
| 62 DCHECK(watcher); | 65 DCHECK(watcher); |
| 63 watcher->ActivateThreadWatching(); | 66 watcher->ActivateThreadWatching(); |
| 64 } | 67 } |
| 65 | 68 |
| 66 void ThreadWatcher::ActivateThreadWatching() { | 69 void ThreadWatcher::ActivateThreadWatching() { |
| 67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 70 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 68 if (active_) return; | 71 if (active_) return; |
| 69 active_ = true; | 72 active_ = true; |
| 70 ping_count_ = kPingCount; | 73 ping_count_ = kPingCount; |
| 71 MessageLoop::current()->PostTask( | 74 MessageLoop::current()->PostTask( |
| 72 FROM_HERE, | 75 FROM_HERE, |
| 73 method_factory_.NewRunnableMethod(&ThreadWatcher::PostPingMessage)); | 76 method_factory_.NewRunnableMethod(&ThreadWatcher::PostPingMessage)); |
| 74 } | 77 } |
| 75 | 78 |
| 76 void ThreadWatcher::DeActivateThreadWatching() { | 79 void ThreadWatcher::DeActivateThreadWatching() { |
| 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 80 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 78 active_ = false; | 81 active_ = false; |
| 79 ping_count_ = 0; | 82 ping_count_ = 0; |
| 80 method_factory_.RevokeAll(); | 83 method_factory_.RevokeAll(); |
| 81 } | 84 } |
| 82 | 85 |
| 83 void ThreadWatcher::WakeUp() { | 86 void ThreadWatcher::WakeUp() { |
| 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 87 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 85 // There is some user activity, PostPingMessage task of thread watcher if | 88 // There is some user activity, PostPingMessage task of thread watcher if |
| 86 // needed. | 89 // needed. |
| 87 if (!active_) return; | 90 if (!active_) return; |
| 88 | 91 |
| 89 if (ping_count_ <= 0) { | 92 if (ping_count_ <= 0) { |
| 90 ping_count_ = kPingCount; | 93 ping_count_ = kPingCount; |
| 91 PostPingMessage(); | 94 PostPingMessage(); |
| 92 } else { | 95 } else { |
| 93 ping_count_ = kPingCount; | 96 ping_count_ = kPingCount; |
| 94 } | 97 } |
| 95 } | 98 } |
| 96 | 99 |
| 97 void ThreadWatcher::PostPingMessage() { | 100 void ThreadWatcher::PostPingMessage() { |
| 98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 101 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 99 // If we have stopped watching or if the user is idle, then stop sending | 102 // If we have stopped watching or if the user is idle, then stop sending |
| 100 // ping messages. | 103 // ping messages. |
| 101 if (!active_ || ping_count_ <= 0) | 104 if (!active_ || ping_count_ <= 0) |
| 102 return; | 105 return; |
| 103 | 106 |
| 104 // Save the current time when we have sent ping message. | 107 // Save the current time when we have sent ping message. |
| 105 ping_time_ = base::TimeTicks::Now(); | 108 ping_time_ = base::TimeTicks::Now(); |
| 106 | 109 |
| 107 // Send a ping message to the watched thread. | 110 // Send a ping message to the watched thread. |
| 108 Task* callback_task = method_factory_.NewRunnableMethod( | 111 Task* callback_task = method_factory_.NewRunnableMethod( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 119 &ThreadWatcher::OnCheckResponsiveness, ping_sequence_number_), | 122 &ThreadWatcher::OnCheckResponsiveness, ping_sequence_number_), |
| 120 unresponsive_time_.InMilliseconds()); | 123 unresponsive_time_.InMilliseconds()); |
| 121 } else { | 124 } else { |
| 122 // Watched thread might have gone away, stop watching it. | 125 // Watched thread might have gone away, stop watching it. |
| 123 delete callback_task; | 126 delete callback_task; |
| 124 DeActivateThreadWatching(); | 127 DeActivateThreadWatching(); |
| 125 } | 128 } |
| 126 } | 129 } |
| 127 | 130 |
| 128 void ThreadWatcher::OnPongMessage(uint64 ping_sequence_number) { | 131 void ThreadWatcher::OnPongMessage(uint64 ping_sequence_number) { |
| 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 132 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 130 // Record watched thread's response time. | 133 // Record watched thread's response time. |
| 131 base::TimeDelta response_time = base::TimeTicks::Now() - ping_time_; | 134 base::TimeDelta response_time = base::TimeTicks::Now() - ping_time_; |
| 132 histogram_->AddTime(response_time); | 135 histogram_->AddTime(response_time); |
| 133 | 136 |
| 134 // Check if there are any extra pings in flight. | 137 // Check if there are any extra pings in flight. |
| 135 DCHECK_EQ(ping_sequence_number_, ping_sequence_number); | 138 DCHECK_EQ(ping_sequence_number_, ping_sequence_number); |
| 136 if (ping_sequence_number_ != ping_sequence_number) | 139 if (ping_sequence_number_ != ping_sequence_number) |
| 137 return; | 140 return; |
| 138 | 141 |
| 139 // Increment sequence number for the next ping message to indicate watched | 142 // Increment sequence number for the next ping message to indicate watched |
| 140 // thread is responsive. | 143 // thread is responsive. |
| 141 ++ping_sequence_number_; | 144 ++ping_sequence_number_; |
| 142 | 145 |
| 143 // If we have stopped watching or if the user is idle, then stop sending | 146 // If we have stopped watching or if the user is idle, then stop sending |
| 144 // ping messages. | 147 // ping messages. |
| 145 if (!active_ || --ping_count_ <= 0) | 148 if (!active_ || --ping_count_ <= 0) |
| 146 return; | 149 return; |
| 147 | 150 |
| 148 MessageLoop::current()->PostDelayedTask( | 151 MessageLoop::current()->PostDelayedTask( |
| 149 FROM_HERE, | 152 FROM_HERE, |
| 150 method_factory_.NewRunnableMethod(&ThreadWatcher::PostPingMessage), | 153 method_factory_.NewRunnableMethod(&ThreadWatcher::PostPingMessage), |
| 151 sleep_time_.InMilliseconds()); | 154 sleep_time_.InMilliseconds()); |
| 152 } | 155 } |
| 153 | 156 |
| 154 bool ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) { | 157 bool ThreadWatcher::OnCheckResponsiveness(uint64 ping_sequence_number) { |
| 155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 158 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 156 // If we have stopped watching then consider thread as responding. | 159 // If we have stopped watching then consider thread as responding. |
| 157 if (!active_) | 160 if (!active_) |
| 158 return true; | 161 return true; |
| 159 // If the latest ping_sequence_number_ is not same as the ping_sequence_number | 162 // If the latest ping_sequence_number_ is not same as the ping_sequence_number |
| 160 // that is passed in, then we can assume OnPongMessage was called. | 163 // that is passed in, then we can assume OnPongMessage was called. |
| 161 // OnPongMessage increments ping_sequence_number_. | 164 // OnPongMessage increments ping_sequence_number_. |
| 162 if (ping_sequence_number_ != ping_sequence_number) | 165 if (ping_sequence_number_ != ping_sequence_number) |
| 163 return true; | 166 return true; |
| 164 return false; | 167 return false; |
| 165 } | 168 } |
| 166 | 169 |
| 167 void ThreadWatcher::Initialize() { | 170 void ThreadWatcher::Initialize() { |
| 168 ThreadWatcherList::Register(this); | 171 ThreadWatcherList::Register(this); |
| 169 histogram_ = base::Histogram::FactoryTimeGet( | 172 histogram_ = base::Histogram::FactoryTimeGet( |
| 170 "ThreadWatcher.ResponseTime." + thread_name_, | 173 "ThreadWatcher.ResponseTime." + thread_name_, |
| 171 base::TimeDelta::FromMilliseconds(1), | 174 base::TimeDelta::FromMilliseconds(1), |
| 172 base::TimeDelta::FromSeconds(100), 50, | 175 base::TimeDelta::FromSeconds(100), 50, |
| 173 base::Histogram::kUmaTargetedHistogramFlag); | 176 base::Histogram::kUmaTargetedHistogramFlag); |
| 174 } | 177 } |
| 175 | 178 |
| 176 // static | 179 // static |
| 177 void ThreadWatcher::OnPingMessage(const BrowserThread::ID thread_id, | 180 void ThreadWatcher::OnPingMessage(const BrowserThread::ID thread_id, |
| 178 Task* callback_task) { | 181 Task* callback_task) { |
| 179 // This method is called on watched thread. | 182 // This method is called on watched thread. |
| 180 DCHECK(BrowserThread::CurrentlyOn(thread_id)); | 183 DCHECK(BrowserThread::CurrentlyOn(thread_id)); |
| 181 BrowserThread::PostTask(BrowserThread::WATCHDOG, FROM_HERE, callback_task); | 184 MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop(); |
| 185 if (message_loop) |
| 186 message_loop->PostTask(FROM_HERE, callback_task); |
| 187 else |
| 188 delete callback_task; |
| 182 } | 189 } |
| 183 | 190 |
| 184 //------------------------------------------------------------------------------ | 191 //------------------------------------------------------------------------------ |
| 185 // ThreadWatcherList methods and members. | 192 // ThreadWatcherList methods and members. |
| 186 | 193 |
| 187 // static | 194 // static |
| 188 ThreadWatcherList* ThreadWatcherList::global_ = NULL; | 195 ThreadWatcherList* ThreadWatcherList::global_ = NULL; |
| 189 | 196 |
| 190 ThreadWatcherList::ThreadWatcherList() | 197 ThreadWatcherList::ThreadWatcherList() |
| 191 : last_wakeup_time_(base::TimeTicks::Now()) { | 198 : last_wakeup_time_(base::TimeTicks::Now()) { |
| 192 // Assert we are not running on WATCHDOG thread. Would be ideal to assert we | 199 // Assert we are not running on WATCHDOG thread. Would be ideal to assert we |
| 193 // are on UI thread, but Unit tests are not running on UI thread. | 200 // are on UI thread, but Unit tests are not running on UI thread. |
| 194 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 201 DCHECK(!WatchDogThread::CurrentlyOnWatchDogThread()); |
| 195 DCHECK(!global_); | 202 CHECK(!global_); |
| 196 global_ = this; | 203 global_ = this; |
| 197 // Register Notifications observer. | 204 // Register Notifications observer. |
| 198 #if defined(OS_WIN) | |
| 199 MetricsService::SetupNotifications(®istrar_, this); | 205 MetricsService::SetupNotifications(®istrar_, this); |
| 200 #endif | |
| 201 } | 206 } |
| 202 | 207 |
| 203 ThreadWatcherList::~ThreadWatcherList() { | 208 ThreadWatcherList::~ThreadWatcherList() { |
| 204 base::AutoLock auto_lock(lock_); | 209 base::AutoLock auto_lock(lock_); |
| 205 while (!registered_.empty()) { | |
| 206 RegistrationList::iterator it = registered_.begin(); | |
| 207 delete it->second; | |
| 208 registered_.erase(it->first); | |
| 209 } | |
| 210 DCHECK(this == global_); | 210 DCHECK(this == global_); |
| 211 global_ = NULL; | 211 global_ = NULL; |
| 212 } | 212 } |
| 213 | 213 |
| 214 // static | 214 // static |
| 215 void ThreadWatcherList::Register(ThreadWatcher* watcher) { | 215 void ThreadWatcherList::Register(ThreadWatcher* watcher) { |
| 216 DCHECK(global_); | 216 DCHECK(global_); |
| 217 base::AutoLock auto_lock(global_->lock_); | 217 base::AutoLock auto_lock(global_->lock_); |
| 218 DCHECK(!global_->PreLockedFind(watcher->thread_id())); | 218 DCHECK(!global_->PreLockedFind(watcher->thread_id())); |
| 219 global_->registered_[watcher->thread_id()] = watcher; | 219 global_->registered_[watcher->thread_id()] = watcher; |
| 220 } | 220 } |
| 221 | 221 |
| 222 // static | 222 // static |
| 223 void ThreadWatcherList::StopWatchingAll() { | 223 void ThreadWatcherList::StopWatchingAll() { |
| 224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 225 if (!global_) | 225 if (!global_) |
| 226 return; | 226 return; |
| 227 base::AutoLock auto_lock(global_->lock_); | 227 |
| 228 for (RegistrationList::iterator it = global_->registered_.begin(); | 228 // Remove all notifications for all watched threads. |
| 229 global_->registered_.end() != it; | 229 RemoveNotifications(); |
| 230 ++it) | 230 |
| 231 BrowserThread::PostTask( | 231 // Delete all thread watcher objects on WatchDogThread. |
| 232 BrowserThread::WATCHDOG, | 232 MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop(); |
| 233 if (message_loop) |
| 234 message_loop->PostTask( |
| 233 FROM_HERE, | 235 FROM_HERE, |
| 234 NewRunnableMethod( | 236 NewRunnableMethod(global_, &ThreadWatcherList::DeleteAll)); |
| 235 it->second, &ThreadWatcher::DeActivateThreadWatching)); | |
| 236 } | 237 } |
| 237 | 238 |
| 238 // static | 239 // static |
| 239 void ThreadWatcherList::RemoveNotifications() { | 240 void ThreadWatcherList::RemoveNotifications() { |
| 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 241 if (!global_) | 242 if (!global_) |
| 242 return; | 243 return; |
| 243 #if defined(OS_WIN) | |
| 244 base::AutoLock auto_lock(global_->lock_); | 244 base::AutoLock auto_lock(global_->lock_); |
| 245 global_->registrar_.RemoveAll(); | 245 global_->registrar_.RemoveAll(); |
| 246 #endif | 246 } |
| 247 |
| 248 void ThreadWatcherList::DeleteAll() { |
| 249 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 250 base::AutoLock auto_lock(lock_); |
| 251 while (!registered_.empty()) { |
| 252 RegistrationList::iterator it = registered_.begin(); |
| 253 delete it->second; |
| 254 registered_.erase(it->first); |
| 255 } |
| 247 } | 256 } |
| 248 | 257 |
| 249 void ThreadWatcherList::Observe(NotificationType type, | 258 void ThreadWatcherList::Observe(NotificationType type, |
| 250 const NotificationSource& source, | 259 const NotificationSource& source, |
| 251 const NotificationDetails& details) { | 260 const NotificationDetails& details) { |
| 252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 253 // There is some user activity, see if thread watchers are to be awakened. | 262 // There is some user activity, see if thread watchers are to be awakened. |
| 254 bool need_to_awaken = false; | 263 bool need_to_awaken = false; |
| 255 base::TimeTicks now = base::TimeTicks::Now(); | 264 base::TimeTicks now = base::TimeTicks::Now(); |
| 256 { | 265 { |
| 257 base::AutoLock lock(lock_); | 266 base::AutoLock lock(lock_); |
| 258 if (now - last_wakeup_time_ > base::TimeDelta::FromSeconds(2)) { | 267 if (now - last_wakeup_time_ > base::TimeDelta::FromSeconds(2)) { |
| 259 need_to_awaken = true; | 268 need_to_awaken = true; |
| 260 last_wakeup_time_ = now; | 269 last_wakeup_time_ = now; |
| 261 } | 270 } |
| 262 } | 271 } |
| 263 if (need_to_awaken) | 272 if (need_to_awaken) { |
| 264 BrowserThread::PostTask( | 273 MessageLoop* message_loop = WatchDogThread::CurrentMessageLoop(); |
| 265 BrowserThread::WATCHDOG, | 274 if (message_loop) |
| 266 FROM_HERE, | 275 message_loop->PostTask( |
| 267 NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll)); | 276 FROM_HERE, |
| 277 NewRunnableMethod(this, &ThreadWatcherList::WakeUpAll)); |
| 278 } |
| 268 } | 279 } |
| 269 | 280 |
| 270 void ThreadWatcherList::WakeUpAll() { | 281 void ThreadWatcherList::WakeUpAll() { |
| 271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WATCHDOG)); | 282 DCHECK(WatchDogThread::CurrentlyOnWatchDogThread()); |
| 272 base::AutoLock auto_lock(lock_); | 283 base::AutoLock auto_lock(lock_); |
| 273 for (RegistrationList::iterator it = global_->registered_.begin(); | 284 for (RegistrationList::iterator it = global_->registered_.begin(); |
| 274 global_->registered_.end() != it; | 285 global_->registered_.end() != it; |
| 275 ++it) | 286 ++it) |
| 276 it->second->WakeUp(); | 287 it->second->WakeUp(); |
| 277 } | 288 } |
| 278 | 289 |
| 279 // static | 290 // static |
| 280 ThreadWatcher* ThreadWatcherList::Find(const BrowserThread::ID thread_id) { | 291 ThreadWatcher* ThreadWatcherList::Find(const BrowserThread::ID thread_id) { |
| 281 DCHECK(global_); | 292 DCHECK(global_); |
| 282 base::AutoLock auto_lock(global_->lock_); | 293 base::AutoLock auto_lock(global_->lock_); |
| 283 return global_->PreLockedFind(thread_id); | 294 return global_->PreLockedFind(thread_id); |
| 284 } | 295 } |
| 285 | 296 |
| 286 ThreadWatcher* ThreadWatcherList::PreLockedFind( | 297 ThreadWatcher* ThreadWatcherList::PreLockedFind( |
| 287 const BrowserThread::ID thread_id) { | 298 const BrowserThread::ID thread_id) { |
| 288 RegistrationList::iterator it = registered_.find(thread_id); | 299 RegistrationList::iterator it = registered_.find(thread_id); |
| 289 if (registered_.end() == it) | 300 if (registered_.end() == it) |
| 290 return NULL; | 301 return NULL; |
| 291 return it->second; | 302 return it->second; |
| 292 } | 303 } |
| 293 | 304 |
| 294 //------------------------------------------------------------------------------ | 305 //------------------------------------------------------------------------------ |
| 295 // WatchDogThread methods and members. | 306 // WatchDogThread methods and members. |
| 296 | 307 |
| 308 // static |
| 309 base::Lock WatchDogThread::lock_; |
| 310 // static |
| 311 WatchDogThread* WatchDogThread::watchdog_thread_ = NULL; |
| 312 |
| 297 // The WatchDogThread object must outlive any tasks posted to the IO thread | 313 // The WatchDogThread object must outlive any tasks posted to the IO thread |
| 298 // before the Quit task. | 314 // before the Quit task. |
| 299 DISABLE_RUNNABLE_METHOD_REFCOUNT(WatchDogThread); | 315 DISABLE_RUNNABLE_METHOD_REFCOUNT(WatchDogThread); |
| 300 | 316 |
| 301 WatchDogThread::WatchDogThread() | 317 WatchDogThread::WatchDogThread() : Thread("WATCHDOG") { |
| 302 : BrowserProcessSubThread(BrowserThread::WATCHDOG) { | |
| 303 } | 318 } |
| 304 | 319 |
| 305 WatchDogThread::~WatchDogThread() { | 320 WatchDogThread::~WatchDogThread() { |
| 306 // Remove all notifications for all watched threads. | |
| 307 ThreadWatcherList::RemoveNotifications(); | |
| 308 // We cannot rely on our base class to stop the thread since we want our | 321 // We cannot rely on our base class to stop the thread since we want our |
| 309 // CleanUp function to run. | 322 // CleanUp function to run. |
| 310 Stop(); | 323 Stop(); |
| 311 } | 324 } |
| 312 | 325 |
| 326 void WatchDogThread::StartWatchingAll() { |
| 327 const base::TimeDelta kSleepTime = base::TimeDelta::FromSeconds(5); |
| 328 const base::TimeDelta kUnresponsiveTime = base::TimeDelta::FromSeconds(10); |
| 329 if (BrowserThread::IsMessageLoopValid(BrowserThread::UI)) |
| 330 ThreadWatcher::StartWatching(BrowserThread::UI, "UI", kSleepTime, |
| 331 kUnresponsiveTime); |
| 332 if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) |
| 333 ThreadWatcher::StartWatching(BrowserThread::IO, "IO", kSleepTime, |
| 334 kUnresponsiveTime); |
| 335 if (BrowserThread::IsMessageLoopValid(BrowserThread::DB)) |
| 336 ThreadWatcher::StartWatching(BrowserThread::DB, "DB", kSleepTime, |
| 337 kUnresponsiveTime); |
| 338 if (BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) |
| 339 ThreadWatcher::StartWatching(BrowserThread::FILE, "FILE", kSleepTime, |
| 340 kUnresponsiveTime); |
| 341 if (BrowserThread::IsMessageLoopValid(BrowserThread::CACHE)) |
| 342 ThreadWatcher::StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, |
| 343 kUnresponsiveTime); |
| 344 } |
| 345 |
| 346 // static |
| 347 MessageLoop* WatchDogThread::CurrentMessageLoop() { |
| 348 base::AutoLock lock(lock_); |
| 349 MessageLoop* message_loop = watchdog_thread_ ? |
| 350 watchdog_thread_->message_loop() : NULL; |
| 351 return message_loop; |
| 352 } |
| 353 |
| 354 // static |
| 355 bool WatchDogThread::CurrentlyOnWatchDogThread() { |
| 356 base::AutoLock lock(lock_); |
| 357 return watchdog_thread_ && |
| 358 watchdog_thread_->message_loop() == MessageLoop::current(); |
| 359 } |
| 360 |
| 313 void WatchDogThread::Init() { | 361 void WatchDogThread::Init() { |
| 314 // This thread shouldn't be allowed to perform any blocking disk I/O. | 362 // This thread shouldn't be allowed to perform any blocking disk I/O. |
| 315 base::ThreadRestrictions::SetIOAllowed(false); | 363 base::ThreadRestrictions::SetIOAllowed(false); |
| 316 | 364 |
| 317 BrowserProcessSubThread::Init(); | 365 #if defined(OS_WIN) |
| 366 // Initializes the COM library on the current thread. |
| 367 CoInitialize(NULL); |
| 368 #endif |
| 318 | 369 |
| 370 base::AutoLock lock(lock_); |
| 371 watchdog_thread_ = this; |
| 372 } |
| 373 |
| 374 void WatchDogThread::CleanUp() { |
| 375 base::AutoLock lock(lock_); |
| 376 watchdog_thread_ = NULL; |
| 377 } |
| 378 |
| 379 void WatchDogThread::CleanUpAfterMessageLoopDestruction() { |
| 319 #if defined(OS_WIN) | 380 #if defined(OS_WIN) |
| 320 const base::TimeDelta kSleepTime = base::TimeDelta::FromSeconds(5); | 381 // Closes the COM library on the current thread. CoInitialize must |
| 321 const base::TimeDelta kUnresponsiveTime = base::TimeDelta::FromSeconds(10); | 382 // be balanced by a corresponding call to CoUninitialize. |
| 322 ThreadWatcher::StartWatching(BrowserThread::UI, "UI", kSleepTime, | 383 CoUninitialize(); |
| 323 kUnresponsiveTime); | |
| 324 ThreadWatcher::StartWatching(BrowserThread::IO, "IO", kSleepTime, | |
| 325 kUnresponsiveTime); | |
| 326 ThreadWatcher::StartWatching(BrowserThread::DB, "DB", kSleepTime, | |
| 327 kUnresponsiveTime); | |
| 328 ThreadWatcher::StartWatching(BrowserThread::FILE, "FILE", kSleepTime, | |
| 329 kUnresponsiveTime); | |
| 330 ThreadWatcher::StartWatching(BrowserThread::CACHE, "CACHE", kSleepTime, | |
| 331 kUnresponsiveTime); | |
| 332 #endif | 384 #endif |
| 333 } | 385 } |
| 334 | |
| 335 #endif // 0 | |
| OLD | NEW |