blob: 89e2a2cdef925ec8bfb90031a363e819b3ffeaf3 [file] [log] [blame]
[email protected]91462212009-04-10 15:09:391// Copyright (c) 2009 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]ea15e982008-08-15 07:31:205#include "base/message_loop.h"
6
[email protected]fc7fb6e2008-08-16 03:09:057#include <algorithm>
8
[email protected]f1ea2fa2008-08-21 22:26:069#include "base/compiler_specific.h"
[email protected]f886b7bf2008-09-10 10:54:0610#include "base/lazy_instance.h"
initial.commitd7cae122008-07-26 21:49:3811#include "base/logging.h"
[email protected]b16ef312008-08-19 18:36:2312#include "base/message_pump_default.h"
initial.commitd7cae122008-07-26 21:49:3813#include "base/string_util.h"
[email protected]f886b7bf2008-09-10 10:54:0614#include "base/thread_local.h"
initial.commitd7cae122008-07-26 21:49:3815
[email protected]96c9ea12008-09-23 21:08:2816#if defined(OS_MACOSX)
17#include "base/message_pump_mac.h"
18#endif
[email protected]36987e92008-09-18 18:46:2619#if defined(OS_POSIX)
20#include "base/message_pump_libevent.h"
[email protected]d680c5c2009-05-14 16:44:2621#include "base/third_party/valgrind/valgrind.h"
[email protected]36987e92008-09-18 18:46:2622#endif
[email protected]e5cd46b2009-04-27 18:17:2423#if defined(OS_LINUX)
[email protected]8fc3a482008-10-03 16:52:5924#include "base/message_pump_glib.h"
25#endif
[email protected]36987e92008-09-18 18:46:2626
[email protected]e1acf6f2008-10-27 20:43:3327using base::Time;
28using base::TimeDelta;
29
[email protected]f886b7bf2008-09-10 10:54:0630// A lazily created thread local storage for quick access to a thread's message
31// loop, if one exists. This should be safe and free of static constructors.
32static base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr(
33 base::LINKER_INITIALIZED);
initial.commitd7cae122008-07-26 21:49:3834
35//------------------------------------------------------------------------------
36
initial.commitd7cae122008-07-26 21:49:3837// Logical events for Histogram profiling. Run with -message-loop-histogrammer
38// to get an accounting of messages and actions taken on each thread.
[email protected]fc7fb6e2008-08-16 03:09:0539static const int kTaskRunEvent = 0x1;
40static const int kTimerEvent = 0x2;
initial.commitd7cae122008-07-26 21:49:3841
42// Provide range of message IDs for use in histogramming and debug display.
43static const int kLeastNonZeroMessageId = 1;
44static const int kMaxMessageId = 1099;
45static const int kNumberOfDistinctMessagesDisplayed = 1100;
46
47//------------------------------------------------------------------------------
48
[email protected]fc7fb6e2008-08-16 03:09:0549#if defined(OS_WIN)
initial.commitd7cae122008-07-26 21:49:3850
initial.commitd7cae122008-07-26 21:49:3851// Upon a SEH exception in this thread, it restores the original unhandled
52// exception filter.
53static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) {
54 ::SetUnhandledExceptionFilter(old_filter);
55 return EXCEPTION_CONTINUE_SEARCH;
56}
57
58// Retrieves a pointer to the current unhandled exception filter. There
59// is no standalone getter method.
60static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
61 LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL;
62 top_filter = ::SetUnhandledExceptionFilter(0);
63 ::SetUnhandledExceptionFilter(top_filter);
64 return top_filter;
65}
66
[email protected]fc7fb6e2008-08-16 03:09:0567#endif // defined(OS_WIN)
68
initial.commitd7cae122008-07-26 21:49:3869//------------------------------------------------------------------------------
70
[email protected]f886b7bf2008-09-10 10:54:0671// static
72MessageLoop* MessageLoop::current() {
73 // TODO(darin): sadly, we cannot enable this yet since people call us even
74 // when they have no intention of using us.
75 //DCHECK(loop) << "Ouch, did you forget to initialize me?";
76 return lazy_tls_ptr.Pointer()->Get();
77}
78
[email protected]4d9bdfaf2008-08-26 05:53:5779MessageLoop::MessageLoop(Type type)
80 : type_(type),
[email protected]a5b94a92008-08-12 23:25:4381 nestable_tasks_allowed_(true),
[email protected]b16ef312008-08-19 18:36:2382 exception_restoration_(false),
[email protected]752578562008-09-07 08:08:2983 state_(NULL),
84 next_sequence_num_(0) {
[email protected]f886b7bf2008-09-10 10:54:0685 DCHECK(!current()) << "should only have one message loop per thread";
86 lazy_tls_ptr.Pointer()->Set(this);
[email protected]4d9bdfaf2008-08-26 05:53:5787
[email protected]fc7fb6e2008-08-16 03:09:0588#if defined(OS_WIN)
[email protected]1a8f5d1d2008-09-25 20:33:0489 // TODO(rvargas): Get rid of the OS guards.
[email protected]9bcbf472008-08-30 00:22:4890 if (type_ == TYPE_DEFAULT) {
91 pump_ = new base::MessagePumpDefault();
[email protected]1a8f5d1d2008-09-25 20:33:0492 } else if (type_ == TYPE_IO) {
93 pump_ = new base::MessagePumpForIO();
[email protected]9bcbf472008-08-30 00:22:4894 } else {
[email protected]1a8f5d1d2008-09-25 20:33:0495 DCHECK(type_ == TYPE_UI);
96 pump_ = new base::MessagePumpForUI();
[email protected]9bcbf472008-08-30 00:22:4897 }
[email protected]36987e92008-09-18 18:46:2698#elif defined(OS_POSIX)
[email protected]96c9ea12008-09-23 21:08:2899 if (type_ == TYPE_UI) {
[email protected]8fc3a482008-10-03 16:52:59100#if defined(OS_MACOSX)
[email protected]96c9ea12008-09-23 21:08:28101 pump_ = base::MessagePumpMac::Create();
[email protected]8fc3a482008-10-03 16:52:59102#elif defined(OS_LINUX)
103 pump_ = new base::MessagePumpForUI();
104#endif // OS_LINUX
105 } else if (type_ == TYPE_IO) {
[email protected]36987e92008-09-18 18:46:26106 pump_ = new base::MessagePumpLibevent();
107 } else {
108 pump_ = new base::MessagePumpDefault();
109 }
[email protected]96c9ea12008-09-23 21:08:28110#endif // OS_POSIX
initial.commitd7cae122008-07-26 21:49:38111}
112
113MessageLoop::~MessageLoop() {
114 DCHECK(this == current());
[email protected]2a127252008-08-05 23:16:41115
116 // Let interested parties have one last shot at accessing this.
117 FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
118 WillDestroyCurrentMessageLoop());
119
[email protected]08de3cde2008-09-09 05:55:35120 DCHECK(!state_);
121
[email protected]001747c2008-09-10 00:37:07122 // Clean up any unprocessed tasks, but take care: deleting a task could
123 // result in the addition of more tasks (e.g., via DeleteSoon). We set a
124 // limit on the number of times we will allow a deleted task to generate more
125 // tasks. Normally, we should only pass through this loop once or twice. If
126 // we end up hitting the loop limit, then it is probably due to one task that
127 // is being stubborn. Inspect the queues to see who is left.
128 bool did_work;
129 for (int i = 0; i < 100; ++i) {
130 DeletePendingTasks();
131 ReloadWorkQueue();
132 // If we end up with empty queues, then break out of the loop.
133 did_work = DeletePendingTasks();
134 if (!did_work)
135 break;
[email protected]08de3cde2008-09-09 05:55:35136 }
[email protected]001747c2008-09-10 00:37:07137 DCHECK(!did_work);
138
139 // OK, now make it so that no one can find us.
[email protected]2b89d22b22008-09-10 11:14:56140 lazy_tls_ptr.Pointer()->Set(NULL);
initial.commitd7cae122008-07-26 21:49:38141}
142
[email protected]2a127252008-08-05 23:16:41143void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {
144 DCHECK(this == current());
145 destruction_observers_.AddObserver(obs);
146}
147
148void MessageLoop::RemoveDestructionObserver(DestructionObserver *obs) {
149 DCHECK(this == current());
150 destruction_observers_.RemoveObserver(obs);
151}
152
[email protected]ea15e982008-08-15 07:31:20153void MessageLoop::Run() {
[email protected]fc7fb6e2008-08-16 03:09:05154 AutoRunState save_state(this);
155 RunHandler();
[email protected]ea15e982008-08-15 07:31:20156}
157
[email protected]7e0e8762008-07-31 13:10:20158void MessageLoop::RunAllPending() {
[email protected]fc7fb6e2008-08-16 03:09:05159 AutoRunState save_state(this);
160 state_->quit_received = true; // Means run until we would otherwise block.
161 RunHandler();
initial.commitd7cae122008-07-26 21:49:38162}
163
164// Runs the loop in two different SEH modes:
165// enable_SEH_restoration_ = false : any unhandled exception goes to the last
166// one that calls SetUnhandledExceptionFilter().
167// enable_SEH_restoration_ = true : any unhandled exception goes to the filter
168// that was existed before the loop was run.
[email protected]fc7fb6e2008-08-16 03:09:05169void MessageLoop::RunHandler() {
170#if defined(OS_WIN)
initial.commitd7cae122008-07-26 21:49:38171 if (exception_restoration_) {
172 LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
173 __try {
[email protected]fc7fb6e2008-08-16 03:09:05174 RunInternal();
initial.commitd7cae122008-07-26 21:49:38175 } __except(SEHFilter(current_filter)) {
176 }
[email protected]fc7fb6e2008-08-16 03:09:05177 return;
initial.commitd7cae122008-07-26 21:49:38178 }
[email protected]fc7fb6e2008-08-16 03:09:05179#endif
180
181 RunInternal();
initial.commitd7cae122008-07-26 21:49:38182}
183
184//------------------------------------------------------------------------------
initial.commitd7cae122008-07-26 21:49:38185
[email protected]fc7fb6e2008-08-16 03:09:05186void MessageLoop::RunInternal() {
187 DCHECK(this == current());
188
initial.commitd7cae122008-07-26 21:49:38189 StartHistogrammer();
190
[email protected]fc7fb6e2008-08-16 03:09:05191#if defined(OS_WIN)
192 if (state_->dispatcher) {
193 pump_win()->RunWithDispatcher(this, state_->dispatcher);
194 return;
[email protected]7e0e8762008-07-31 13:10:20195 }
[email protected]fc7fb6e2008-08-16 03:09:05196#endif
[email protected]1d2eb132008-12-08 17:36:06197
[email protected]fc7fb6e2008-08-16 03:09:05198 pump_->Run(this);
[email protected]b8f2fe5d2008-07-30 07:50:53199}
[email protected]7622bd02008-07-30 06:58:56200
[email protected]3882c4332008-07-30 19:03:59201//------------------------------------------------------------------------------
202// Wrapper functions for use in above message loop framework.
203
initial.commitd7cae122008-07-26 21:49:38204bool MessageLoop::ProcessNextDelayedNonNestableTask() {
[email protected]fc7fb6e2008-08-16 03:09:05205 if (state_->run_depth != 1)
initial.commitd7cae122008-07-26 21:49:38206 return false;
207
[email protected]752578562008-09-07 08:08:29208 if (deferred_non_nestable_work_queue_.empty())
initial.commitd7cae122008-07-26 21:49:38209 return false;
[email protected]1d2eb132008-12-08 17:36:06210
[email protected]752578562008-09-07 08:08:29211 Task* task = deferred_non_nestable_work_queue_.front().task;
212 deferred_non_nestable_work_queue_.pop();
[email protected]1d2eb132008-12-08 17:36:06213
[email protected]752578562008-09-07 08:08:29214 RunTask(task);
initial.commitd7cae122008-07-26 21:49:38215 return true;
216}
217
initial.commitd7cae122008-07-26 21:49:38218//------------------------------------------------------------------------------
219
220void MessageLoop::Quit() {
[email protected]fc7fb6e2008-08-16 03:09:05221 DCHECK(current() == this);
222 if (state_) {
223 state_->quit_received = true;
224 } else {
225 NOTREACHED() << "Must be inside Run to call Quit";
initial.commitd7cae122008-07-26 21:49:38226 }
initial.commitd7cae122008-07-26 21:49:38227}
228
[email protected]752578562008-09-07 08:08:29229void MessageLoop::PostTask(
230 const tracked_objects::Location& from_here, Task* task) {
231 PostTask_Helper(from_here, task, 0, true);
232}
233
234void MessageLoop::PostDelayedTask(
[email protected]743ace42009-06-17 17:23:51235 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
[email protected]752578562008-09-07 08:08:29236 PostTask_Helper(from_here, task, delay_ms, true);
237}
238
239void MessageLoop::PostNonNestableTask(
240 const tracked_objects::Location& from_here, Task* task) {
241 PostTask_Helper(from_here, task, 0, false);
242}
243
244void MessageLoop::PostNonNestableDelayedTask(
[email protected]743ace42009-06-17 17:23:51245 const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
[email protected]752578562008-09-07 08:08:29246 PostTask_Helper(from_here, task, delay_ms, false);
247}
248
initial.commitd7cae122008-07-26 21:49:38249// Possibly called on a background thread!
[email protected]752578562008-09-07 08:08:29250void MessageLoop::PostTask_Helper(
[email protected]743ace42009-06-17 17:23:51251 const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
[email protected]752578562008-09-07 08:08:29252 bool nestable) {
initial.commitd7cae122008-07-26 21:49:38253 task->SetBirthPlace(from_here);
[email protected]9bcbf472008-08-30 00:22:48254
[email protected]752578562008-09-07 08:08:29255 PendingTask pending_task(task, nestable);
[email protected]9bcbf472008-08-30 00:22:48256
257 if (delay_ms > 0) {
[email protected]752578562008-09-07 08:08:29258 pending_task.delayed_run_time =
[email protected]9bcbf472008-08-30 00:22:48259 Time::Now() + TimeDelta::FromMilliseconds(delay_ms);
260 } else {
261 DCHECK(delay_ms == 0) << "delay should not be negative";
262 }
263
initial.commitd7cae122008-07-26 21:49:38264 // Warning: Don't try to short-circuit, and handle this thread's tasks more
265 // directly, as it could starve handling of foreign threads. Put every task
266 // into this queue.
267
[email protected]fc7fb6e2008-08-16 03:09:05268 scoped_refptr<base::MessagePump> pump;
initial.commitd7cae122008-07-26 21:49:38269 {
[email protected]fc7fb6e2008-08-16 03:09:05270 AutoLock locked(incoming_queue_lock_);
271
[email protected]752578562008-09-07 08:08:29272 bool was_empty = incoming_queue_.empty();
273 incoming_queue_.push(pending_task);
initial.commitd7cae122008-07-26 21:49:38274 if (!was_empty)
275 return; // Someone else should have started the sub-pump.
276
[email protected]fc7fb6e2008-08-16 03:09:05277 pump = pump_;
[email protected]ea15e982008-08-15 07:31:20278 }
[email protected]fc7fb6e2008-08-16 03:09:05279 // Since the incoming_queue_ may contain a task that destroys this message
280 // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
281 // We use a stack-based reference to the message pump so that we can call
282 // ScheduleWork outside of incoming_queue_lock_.
[email protected]ea15e982008-08-15 07:31:20283
[email protected]fc7fb6e2008-08-16 03:09:05284 pump->ScheduleWork();
initial.commitd7cae122008-07-26 21:49:38285}
286
287void MessageLoop::SetNestableTasksAllowed(bool allowed) {
[email protected]124a2bdf2008-08-09 00:14:09288 if (nestable_tasks_allowed_ != allowed) {
289 nestable_tasks_allowed_ = allowed;
290 if (!nestable_tasks_allowed_)
291 return;
292 // Start the native pump if we are not already pumping.
[email protected]fc7fb6e2008-08-16 03:09:05293 pump_->ScheduleWork();
[email protected]124a2bdf2008-08-09 00:14:09294 }
initial.commitd7cae122008-07-26 21:49:38295}
296
297bool MessageLoop::NestableTasksAllowed() const {
298 return nestable_tasks_allowed_;
299}
300
initial.commitd7cae122008-07-26 21:49:38301//------------------------------------------------------------------------------
initial.commitd7cae122008-07-26 21:49:38302
initial.commitd7cae122008-07-26 21:49:38303void MessageLoop::RunTask(Task* task) {
initial.commitd7cae122008-07-26 21:49:38304 DCHECK(nestable_tasks_allowed_);
305 // Execute the task and assume the worst: It is probably not reentrant.
306 nestable_tasks_allowed_ = false;
[email protected]752578562008-09-07 08:08:29307
308 HistogramEvent(kTaskRunEvent);
309 task->Run();
310 delete task;
311
312 nestable_tasks_allowed_ = true;
initial.commitd7cae122008-07-26 21:49:38313}
314
[email protected]752578562008-09-07 08:08:29315bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
316 if (pending_task.nestable || state_->run_depth == 1) {
317 RunTask(pending_task.task);
318 // Show that we ran a task (Note: a new one might arrive as a
319 // consequence!).
320 return true;
321 }
322
323 // We couldn't run the task now because we're in a nested message loop
324 // and the task isn't nestable.
325 deferred_non_nestable_work_queue_.push(pending_task);
326 return false;
initial.commitd7cae122008-07-26 21:49:38327}
328
[email protected]001747c2008-09-10 00:37:07329void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
330 // Move to the delayed work queue. Initialize the sequence number
331 // before inserting into the delayed_work_queue_. The sequence number
332 // is used to faciliate FIFO sorting when two tasks have the same
333 // delayed_run_time value.
334 PendingTask new_pending_task(pending_task);
335 new_pending_task.sequence_num = next_sequence_num_++;
336 delayed_work_queue_.push(new_pending_task);
337}
338
initial.commitd7cae122008-07-26 21:49:38339void MessageLoop::ReloadWorkQueue() {
340 // We can improve performance of our loading tasks from incoming_queue_ to
[email protected]fc7fb6e2008-08-16 03:09:05341 // work_queue_ by waiting until the last minute (work_queue_ is empty) to
342 // load. That reduces the number of locks-per-task significantly when our
[email protected]752578562008-09-07 08:08:29343 // queues get large.
344 if (!work_queue_.empty())
initial.commitd7cae122008-07-26 21:49:38345 return; // Wait till we *really* need to lock and load.
346
347 // Acquire all we can from the inter-thread queue with one lock acquisition.
initial.commitd7cae122008-07-26 21:49:38348 {
349 AutoLock lock(incoming_queue_lock_);
[email protected]752578562008-09-07 08:08:29350 if (incoming_queue_.empty())
initial.commitd7cae122008-07-26 21:49:38351 return;
[email protected]752578562008-09-07 08:08:29352 std::swap(incoming_queue_, work_queue_);
353 DCHECK(incoming_queue_.empty());
initial.commitd7cae122008-07-26 21:49:38354 }
355}
356
[email protected]001747c2008-09-10 00:37:07357bool MessageLoop::DeletePendingTasks() {
358 bool did_work = !work_queue_.empty();
359 while (!work_queue_.empty()) {
360 PendingTask pending_task = work_queue_.front();
361 work_queue_.pop();
362 if (!pending_task.delayed_run_time.is_null()) {
363 // We want to delete delayed tasks in the same order in which they would
364 // normally be deleted in case of any funny dependencies between delayed
365 // tasks.
366 AddToDelayedWorkQueue(pending_task);
367 } else {
368 // TODO(darin): Delete all tasks once it is safe to do so.
[email protected]d680c5c2009-05-14 16:44:26369 // Until it is totally safe, just do it when running Purify or
370 // Valgrind.
371#if defined(OS_WIN)
[email protected]20472832009-03-11 19:46:41372#ifdef PURIFY
[email protected]404ec5e2009-03-11 20:06:02373 delete pending_task.task;
[email protected]20472832009-03-11 19:46:41374#endif // PURIFY
[email protected]d680c5c2009-05-14 16:44:26375#elif defined(OS_POSIX)
376 if (RUNNING_ON_VALGRIND)
377 delete pending_task.task;
378#endif // defined(OS_POSIX)
[email protected]001747c2008-09-10 00:37:07379 }
initial.commitd7cae122008-07-26 21:49:38380 }
[email protected]001747c2008-09-10 00:37:07381 did_work |= !deferred_non_nestable_work_queue_.empty();
382 while (!deferred_non_nestable_work_queue_.empty()) {
[email protected]20472832009-03-11 19:46:41383 // TODO(darin): Delete all tasks once it is safe to do so.
384 // Until it is totaly safe, just delete them to keep purify happy.
385#ifdef PURIFY
[email protected]8df21d32009-03-11 19:53:50386 Task* task = deferred_non_nestable_work_queue_.front().task;
387#endif
388 deferred_non_nestable_work_queue_.pop();
389#ifdef PURIFY
[email protected]20472832009-03-11 19:46:41390 delete task;
391#endif
initial.commitd7cae122008-07-26 21:49:38392 }
[email protected]001747c2008-09-10 00:37:07393 did_work |= !delayed_work_queue_.empty();
394 while (!delayed_work_queue_.empty()) {
395 Task* task = delayed_work_queue_.top().task;
396 delayed_work_queue_.pop();
397 delete task;
398 }
399 return did_work;
initial.commitd7cae122008-07-26 21:49:38400}
401
[email protected]fc7fb6e2008-08-16 03:09:05402bool MessageLoop::DoWork() {
[email protected]752578562008-09-07 08:08:29403 if (!nestable_tasks_allowed_) {
404 // Task can't be executed right now.
405 return false;
406 }
407
408 for (;;) {
409 ReloadWorkQueue();
410 if (work_queue_.empty())
411 break;
412
413 // Execute oldest task.
414 do {
415 PendingTask pending_task = work_queue_.front();
416 work_queue_.pop();
417 if (!pending_task.delayed_run_time.is_null()) {
[email protected]001747c2008-09-10 00:37:07418 AddToDelayedWorkQueue(pending_task);
[email protected]72deacd2008-09-23 19:19:20419 // If we changed the topmost task, then it is time to re-schedule.
420 if (delayed_work_queue_.top().task == pending_task.task)
[email protected]752578562008-09-07 08:08:29421 pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
422 } else {
423 if (DeferOrRunPendingTask(pending_task))
424 return true;
425 }
426 } while (!work_queue_.empty());
427 }
428
429 // Nothing happened.
430 return false;
[email protected]fc7fb6e2008-08-16 03:09:05431}
432
[email protected]b24250fc2008-08-20 06:30:58433bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) {
[email protected]752578562008-09-07 08:08:29434 if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
435 *next_delayed_work_time = Time();
436 return false;
437 }
[email protected]1d2eb132008-12-08 17:36:06438
[email protected]752578562008-09-07 08:08:29439 if (delayed_work_queue_.top().delayed_run_time > Time::Now()) {
440 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
441 return false;
442 }
[email protected]fc7fb6e2008-08-16 03:09:05443
[email protected]752578562008-09-07 08:08:29444 PendingTask pending_task = delayed_work_queue_.top();
445 delayed_work_queue_.pop();
[email protected]1d2eb132008-12-08 17:36:06446
[email protected]752578562008-09-07 08:08:29447 if (!delayed_work_queue_.empty())
448 *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
[email protected]fc7fb6e2008-08-16 03:09:05449
[email protected]752578562008-09-07 08:08:29450 return DeferOrRunPendingTask(pending_task);
[email protected]fc7fb6e2008-08-16 03:09:05451}
452
453bool MessageLoop::DoIdleWork() {
454 if (ProcessNextDelayedNonNestableTask())
455 return true;
456
457 if (state_->quit_received)
458 pump_->Quit();
459
460 return false;
461}
462
463//------------------------------------------------------------------------------
464// MessageLoop::AutoRunState
465
466MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
467 // Make the loop reference us.
468 previous_state_ = loop_->state_;
469 if (previous_state_) {
470 run_depth = previous_state_->run_depth + 1;
[email protected]ea15e982008-08-15 07:31:20471 } else {
[email protected]fc7fb6e2008-08-16 03:09:05472 run_depth = 1;
[email protected]ea15e982008-08-15 07:31:20473 }
[email protected]fc7fb6e2008-08-16 03:09:05474 loop_->state_ = this;
475
476 // Initialize the other fields:
477 quit_received = false;
478#if defined(OS_WIN)
479 dispatcher = NULL;
480#endif
481}
482
483MessageLoop::AutoRunState::~AutoRunState() {
484 loop_->state_ = previous_state_;
[email protected]a5b94a92008-08-12 23:25:43485}
486
initial.commitd7cae122008-07-26 21:49:38487//------------------------------------------------------------------------------
[email protected]752578562008-09-07 08:08:29488// MessageLoop::PendingTask
initial.commitd7cae122008-07-26 21:49:38489
[email protected]752578562008-09-07 08:08:29490bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
491 // Since the top of a priority queue is defined as the "greatest" element, we
492 // need to invert the comparison here. We want the smaller time to be at the
493 // top of the heap.
initial.commitd7cae122008-07-26 21:49:38494
[email protected]752578562008-09-07 08:08:29495 if (delayed_run_time < other.delayed_run_time)
496 return false;
initial.commitd7cae122008-07-26 21:49:38497
[email protected]752578562008-09-07 08:08:29498 if (delayed_run_time > other.delayed_run_time)
499 return true;
initial.commitd7cae122008-07-26 21:49:38500
[email protected]752578562008-09-07 08:08:29501 // If the times happen to match, then we use the sequence number to decide.
502 // Compare the difference to support integer roll-over.
503 return (sequence_num - other.sequence_num) > 0;
initial.commitd7cae122008-07-26 21:49:38504}
505
506//------------------------------------------------------------------------------
507// Method and data for histogramming events and actions taken by each instance
508// on each thread.
509
510// static
511bool MessageLoop::enable_histogrammer_ = false;
512
513// static
514void MessageLoop::EnableHistogrammer(bool enable) {
515 enable_histogrammer_ = enable;
516}
517
518void MessageLoop::StartHistogrammer() {
519 if (enable_histogrammer_ && !message_histogram_.get()
520 && StatisticsRecorder::WasStarted()) {
[email protected]fc7fb6e2008-08-16 03:09:05521 DCHECK(!thread_name_.empty());
[email protected]553dba62009-02-24 19:08:23522 message_histogram_.reset(
523 new LinearHistogram(("MsgLoop:" + thread_name_).c_str(),
524 kLeastNonZeroMessageId,
525 kMaxMessageId,
526 kNumberOfDistinctMessagesDisplayed));
initial.commitd7cae122008-07-26 21:49:38527 message_histogram_->SetFlags(message_histogram_->kHexRangePrintingFlag);
528 message_histogram_->SetRangeDescriptions(event_descriptions_);
529 }
530}
531
532void MessageLoop::HistogramEvent(int event) {
533 if (message_histogram_.get())
534 message_histogram_->Add(event);
535}
536
initial.commitd7cae122008-07-26 21:49:38537// Provide a macro that takes an expression (such as a constant, or macro
538// constant) and creates a pair to initalize an array of pairs. In this case,
539// our pair consists of the expressions value, and the "stringized" version
540// of the expression (i.e., the exrpression put in quotes). For example, if
541// we have:
542// #define FOO 2
543// #define BAR 5
544// then the following:
545// VALUE_TO_NUMBER_AND_NAME(FOO + BAR)
546// will expand to:
547// {7, "FOO + BAR"}
548// We use the resulting array as an argument to our histogram, which reads the
549// number as a bucket identifier, and proceeds to use the corresponding name
550// in the pair (i.e., the quoted string) when printing out a histogram.
551#define VALUE_TO_NUMBER_AND_NAME(name) {name, #name},
552
initial.commitd7cae122008-07-26 21:49:38553// static
554const LinearHistogram::DescriptionPair MessageLoop::event_descriptions_[] = {
initial.commitd7cae122008-07-26 21:49:38555 // Provide some pretty print capability in our histogram for our internal
556 // messages.
557
initial.commitd7cae122008-07-26 21:49:38558 // A few events we handle (kindred to messages), and used to profile actions.
559 VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent)
initial.commitd7cae122008-07-26 21:49:38560 VALUE_TO_NUMBER_AND_NAME(kTimerEvent)
561
562 {-1, NULL} // The list must be null terminated, per API to histogram.
563};
license.botbf09a502008-08-24 00:55:55564
[email protected]4d9bdfaf2008-08-26 05:53:57565//------------------------------------------------------------------------------
566// MessageLoopForUI
567
[email protected]faabcf42009-05-18 21:12:34568#if defined(OS_LINUX) || defined(OS_WIN)
569
570void MessageLoopForUI::AddObserver(Observer* observer) {
571 pump_ui()->AddObserver(observer);
572}
573
574void MessageLoopForUI::RemoveObserver(Observer* observer) {
575 pump_ui()->RemoveObserver(observer);
576}
577
578#endif
579
[email protected]4d9bdfaf2008-08-26 05:53:57580#if defined(OS_WIN)
581
582void MessageLoopForUI::Run(Dispatcher* dispatcher) {
583 AutoRunState save_state(this);
584 state_->dispatcher = dispatcher;
585 RunHandler();
586}
587
[email protected]4d9bdfaf2008-08-26 05:53:57588void MessageLoopForUI::WillProcessMessage(const MSG& message) {
589 pump_win()->WillProcessMessage(message);
590}
591void MessageLoopForUI::DidProcessMessage(const MSG& message) {
592 pump_win()->DidProcessMessage(message);
593}
594void MessageLoopForUI::PumpOutPendingPaintMessages() {
[email protected]17b89142008-11-07 21:52:15595 pump_ui()->PumpOutPendingPaintMessages();
[email protected]4d9bdfaf2008-08-26 05:53:57596}
597
598#endif // defined(OS_WIN)
599
600//------------------------------------------------------------------------------
601// MessageLoopForIO
602
603#if defined(OS_WIN)
604
[email protected]32cda29d2008-10-09 23:58:43605void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
606 pump_io()->RegisterIOHandler(file, handler);
607}
608
[email protected]17b89142008-11-07 21:52:15609bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
610 return pump_io()->WaitForIOCompletion(timeout, filter);
[email protected]32cda29d2008-10-09 23:58:43611}
612
[email protected]36987e92008-09-18 18:46:26613#elif defined(OS_POSIX)
614
[email protected]e45e6c02008-12-15 22:02:17615bool MessageLoopForIO::WatchFileDescriptor(int fd,
616 bool persistent,
617 Mode mode,
618 FileDescriptorWatcher *controller,
619 Watcher *delegate) {
620 return pump_libevent()->WatchFileDescriptor(
621 fd,
622 persistent,
623 static_cast<base::MessagePumpLibevent::Mode>(mode),
624 controller,
625 delegate);
[email protected]36987e92008-09-18 18:46:26626}
627
[email protected]36987e92008-09-18 18:46:26628#endif