1 : // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "base/message_loop.h"
6 :
7 : #include <algorithm>
8 :
9 : #include "base/compiler_specific.h"
10 : #include "base/lazy_instance.h"
11 : #include "base/logging.h"
12 : #include "base/message_pump_default.h"
13 : #include "base/string_util.h"
14 : #include "base/thread_local.h"
15 :
16 : #if defined(OS_MACOSX)
17 : #include "base/message_pump_mac.h"
18 : #endif
19 : #if defined(OS_POSIX)
20 : #include "base/message_pump_libevent.h"
21 : #endif
22 : #if defined(OS_LINUX)
23 : #ifdef MOZ_WIDGET_GTK2
24 : #include "base/message_pump_glib.h"
25 : #endif
26 : #ifdef MOZ_WIDGET_QT
27 : #include "base/message_pump_qt.h"
28 : #endif
29 : #endif
30 : #ifdef ANDROID
31 : #include "base/message_pump_android.h"
32 : #endif
33 :
34 : #include "MessagePump.h"
35 :
36 : using base::Time;
37 : using base::TimeDelta;
38 :
39 : // A lazily created thread local storage for quick access to a thread's message
40 : // loop, if one exists. This should be safe and free of static constructors.
41 : static base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr(
42 1464 : base::LINKER_INITIALIZED);
43 :
44 : //------------------------------------------------------------------------------
45 :
46 : // Logical events for Histogram profiling. Run with -message-loop-histogrammer
47 : // to get an accounting of messages and actions taken on each thread.
48 : static const int kTaskRunEvent = 0x1;
49 : static const int kTimerEvent = 0x2;
50 :
51 : // Provide range of message IDs for use in histogramming and debug display.
52 : static const int kLeastNonZeroMessageId = 1;
53 : static const int kMaxMessageId = 1099;
54 : static const int kNumberOfDistinctMessagesDisplayed = 1100;
55 :
56 : //------------------------------------------------------------------------------
57 :
58 : #if defined(OS_WIN)
59 :
60 : // Upon a SEH exception in this thread, it restores the original unhandled
61 : // exception filter.
62 : static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) {
63 : ::SetUnhandledExceptionFilter(old_filter);
64 : return EXCEPTION_CONTINUE_SEARCH;
65 : }
66 :
67 : // Retrieves a pointer to the current unhandled exception filter. There
68 : // is no standalone getter method.
69 : static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
70 : LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL;
71 : top_filter = ::SetUnhandledExceptionFilter(0);
72 : ::SetUnhandledExceptionFilter(top_filter);
73 : return top_filter;
74 : }
75 :
76 : #endif // defined(OS_WIN)
77 :
78 : //------------------------------------------------------------------------------
79 :
80 : // static
81 11360 : MessageLoop* MessageLoop::current() {
82 : // TODO(darin): sadly, we cannot enable this yet since people call us even
83 : // when they have no intention of using us.
84 : //DCHECK(loop) << "Ouch, did you forget to initialize me?";
85 11360 : return lazy_tls_ptr.Pointer()->Get();
86 : }
87 :
88 2840 : MessageLoop::MessageLoop(Type type)
89 : : type_(type),
90 : nestable_tasks_allowed_(true),
91 : exception_restoration_(false),
92 : state_(NULL),
93 : #ifdef OS_WIN
94 : os_modal_loop_(false),
95 : #endif // OS_WIN
96 2840 : next_sequence_num_(0) {
97 2840 : DCHECK(!current()) << "should only have one message loop per thread";
98 2840 : lazy_tls_ptr.Pointer()->Set(this);
99 2840 : if (type_ == TYPE_MOZILLA_UI) {
100 1419 : pump_ = new mozilla::ipc::MessagePump();
101 1419 : return;
102 : }
103 1421 : if (type_ == TYPE_MOZILLA_CHILD) {
104 1 : pump_ = new mozilla::ipc::MessagePumpForChildProcess();
105 1 : return;
106 : }
107 :
108 : #if defined(OS_WIN)
109 : // TODO(rvargas): Get rid of the OS guards.
110 : if (type_ == TYPE_DEFAULT) {
111 : pump_ = new base::MessagePumpDefault();
112 : } else if (type_ == TYPE_IO) {
113 : pump_ = new base::MessagePumpForIO();
114 : } else {
115 : DCHECK(type_ == TYPE_UI);
116 : pump_ = new base::MessagePumpForUI();
117 : }
118 : #elif defined(OS_POSIX)
119 1420 : if (type_ == TYPE_UI) {
120 : #if defined(OS_MACOSX)
121 : pump_ = base::MessagePumpMac::Create();
122 : #elif defined(OS_LINUX)
123 0 : pump_ = new base::MessagePumpForUI();
124 : #endif // OS_LINUX
125 1420 : } else if (type_ == TYPE_IO) {
126 1420 : pump_ = new base::MessagePumpLibevent();
127 : } else {
128 0 : pump_ = new base::MessagePumpDefault();
129 : }
130 : #endif // OS_POSIX
131 : }
132 :
133 5676 : MessageLoop::~MessageLoop() {
134 2838 : DCHECK(this == current());
135 :
136 : // Let interested parties have one last shot at accessing this.
137 2838 : FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
138 : WillDestroyCurrentMessageLoop());
139 :
140 2838 : DCHECK(!state_);
141 :
142 : // Clean up any unprocessed tasks, but take care: deleting a task could
143 : // result in the addition of more tasks (e.g., via DeleteSoon). We set a
144 : // limit on the number of times we will allow a deleted task to generate more
145 : // tasks. Normally, we should only pass through this loop once or twice. If
146 : // we end up hitting the loop limit, then it is probably due to one task that
147 : // is being stubborn. Inspect the queues to see who is left.
148 : bool did_work;
149 2838 : for (int i = 0; i < 100; ++i) {
150 2838 : DeletePendingTasks();
151 2838 : ReloadWorkQueue();
152 : // If we end up with empty queues, then break out of the loop.
153 2838 : did_work = DeletePendingTasks();
154 2838 : if (!did_work)
155 2838 : break;
156 : }
157 2838 : DCHECK(!did_work);
158 :
159 : // OK, now make it so that no one can find us.
160 2838 : lazy_tls_ptr.Pointer()->Set(NULL);
161 5676 : }
162 :
163 1 : void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {
164 1 : DCHECK(this == current());
165 1 : destruction_observers_.AddObserver(obs);
166 1 : }
167 :
168 0 : void MessageLoop::RemoveDestructionObserver(DestructionObserver *obs) {
169 0 : DCHECK(this == current());
170 0 : destruction_observers_.RemoveObserver(obs);
171 0 : }
172 :
173 1420 : void MessageLoop::Run() {
174 2839 : AutoRunState save_state(this);
175 1420 : RunHandler();
176 1419 : }
177 :
178 0 : void MessageLoop::RunAllPending() {
179 0 : AutoRunState save_state(this);
180 0 : state_->quit_received = true; // Means run until we would otherwise block.
181 0 : RunHandler();
182 0 : }
183 :
184 : // Runs the loop in two different SEH modes:
185 : // enable_SEH_restoration_ = false : any unhandled exception goes to the last
186 : // one that calls SetUnhandledExceptionFilter().
187 : // enable_SEH_restoration_ = true : any unhandled exception goes to the filter
188 : // that was existed before the loop was run.
189 1420 : void MessageLoop::RunHandler() {
190 : #if defined(OS_WIN)
191 : if (exception_restoration_) {
192 : LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
193 : MOZ_SEH_TRY {
194 : RunInternal();
195 : } MOZ_SEH_EXCEPT(SEHFilter(current_filter)) {
196 : }
197 : return;
198 : }
199 : #endif
200 :
201 1420 : RunInternal();
202 1419 : }
203 :
204 : //------------------------------------------------------------------------------
205 :
206 1420 : void MessageLoop::RunInternal() {
207 1420 : DCHECK(this == current());
208 1420 : pump_->Run(this);
209 1419 : }
210 :
211 : //------------------------------------------------------------------------------
212 : // Wrapper functions for use in above message loop framework.
213 :
214 2839 : bool MessageLoop::ProcessNextDelayedNonNestableTask() {
215 2839 : if (state_->run_depth != 1)
216 0 : return false;
217 :
218 2839 : if (deferred_non_nestable_work_queue_.empty())
219 2839 : return false;
220 :
221 0 : Task* task = deferred_non_nestable_work_queue_.front().task;
222 0 : deferred_non_nestable_work_queue_.pop();
223 :
224 0 : RunTask(task);
225 0 : return true;
226 : }
227 :
228 : //------------------------------------------------------------------------------
229 :
230 1419 : void MessageLoop::Quit() {
231 1419 : DCHECK(current() == this);
232 1419 : if (state_) {
233 1419 : state_->quit_received = true;
234 : } else {
235 0 : NOTREACHED() << "Must be inside Run to call Quit";
236 : }
237 1419 : }
238 :
239 1419 : void MessageLoop::PostTask(
240 : const tracked_objects::Location& from_here, Task* task) {
241 1419 : PostTask_Helper(from_here, task, 0, true);
242 1419 : }
243 :
244 0 : void MessageLoop::PostDelayedTask(
245 : const tracked_objects::Location& from_here, Task* task, int delay_ms) {
246 0 : PostTask_Helper(from_here, task, delay_ms, true);
247 0 : }
248 :
249 0 : void MessageLoop::PostNonNestableTask(
250 : const tracked_objects::Location& from_here, Task* task) {
251 0 : PostTask_Helper(from_here, task, 0, false);
252 0 : }
253 :
254 0 : void MessageLoop::PostNonNestableDelayedTask(
255 : const tracked_objects::Location& from_here, Task* task, int delay_ms) {
256 0 : PostTask_Helper(from_here, task, delay_ms, false);
257 0 : }
258 :
259 : // Possibly called on a background thread!
260 1419 : void MessageLoop::PostTask_Helper(
261 : const tracked_objects::Location& from_here, Task* task, int delay_ms,
262 : bool nestable) {
263 1419 : task->SetBirthPlace(from_here);
264 :
265 1419 : PendingTask pending_task(task, nestable);
266 :
267 1419 : if (delay_ms > 0) {
268 : pending_task.delayed_run_time =
269 0 : Time::Now() + TimeDelta::FromMilliseconds(delay_ms);
270 : } else {
271 1419 : DCHECK(delay_ms == 0) << "delay should not be negative";
272 : }
273 :
274 : // Warning: Don't try to short-circuit, and handle this thread's tasks more
275 : // directly, as it could starve handling of foreign threads. Put every task
276 : // into this queue.
277 :
278 2838 : scoped_refptr<base::MessagePump> pump;
279 : {
280 2838 : AutoLock locked(incoming_queue_lock_);
281 1419 : incoming_queue_.push(pending_task);
282 1419 : pump = pump_;
283 : }
284 : // Since the incoming_queue_ may contain a task that destroys this message
285 : // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
286 : // We use a stack-based reference to the message pump so that we can call
287 : // ScheduleWork outside of incoming_queue_lock_.
288 :
289 1419 : pump->ScheduleWork();
290 1419 : }
291 :
292 0 : void MessageLoop::SetNestableTasksAllowed(bool allowed) {
293 0 : if (nestable_tasks_allowed_ != allowed) {
294 0 : nestable_tasks_allowed_ = allowed;
295 0 : if (!nestable_tasks_allowed_)
296 0 : return;
297 : // Start the native pump if we are not already pumping.
298 0 : pump_->ScheduleWorkForNestedLoop();
299 : }
300 : }
301 :
302 0 : void MessageLoop::ScheduleWork() {
303 : // Start the native pump if we are not already pumping.
304 0 : pump_->ScheduleWork();
305 0 : }
306 :
307 0 : bool MessageLoop::NestableTasksAllowed() const {
308 0 : return nestable_tasks_allowed_;
309 : }
310 :
311 : //------------------------------------------------------------------------------
312 :
313 1419 : void MessageLoop::RunTask(Task* task) {
314 1419 : DCHECK(nestable_tasks_allowed_);
315 : // Execute the task and assume the worst: It is probably not reentrant.
316 1419 : nestable_tasks_allowed_ = false;
317 :
318 1419 : task->Run();
319 1419 : delete task;
320 :
321 1419 : nestable_tasks_allowed_ = true;
322 1419 : }
323 :
324 1419 : bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
325 1419 : if (pending_task.nestable || state_->run_depth == 1) {
326 1419 : RunTask(pending_task.task);
327 : // Show that we ran a task (Note: a new one might arrive as a
328 : // consequence!).
329 1419 : return true;
330 : }
331 :
332 : // We couldn't run the task now because we're in a nested message loop
333 : // and the task isn't nestable.
334 0 : deferred_non_nestable_work_queue_.push(pending_task);
335 0 : return false;
336 : }
337 :
338 0 : void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
339 : // Move to the delayed work queue. Initialize the sequence number
340 : // before inserting into the delayed_work_queue_. The sequence number
341 : // is used to faciliate FIFO sorting when two tasks have the same
342 : // delayed_run_time value.
343 0 : PendingTask new_pending_task(pending_task);
344 0 : new_pending_task.sequence_num = next_sequence_num_++;
345 0 : delayed_work_queue_.push(new_pending_task);
346 0 : }
347 :
348 7096 : void MessageLoop::ReloadWorkQueue() {
349 : // We can improve performance of our loading tasks from incoming_queue_ to
350 : // work_queue_ by waiting until the last minute (work_queue_ is empty) to
351 : // load. That reduces the number of locks-per-task significantly when our
352 : // queues get large.
353 7096 : if (!work_queue_.empty())
354 0 : return; // Wait till we *really* need to lock and load.
355 :
356 : // Acquire all we can from the inter-thread queue with one lock acquisition.
357 : {
358 14192 : AutoLock lock(incoming_queue_lock_);
359 7096 : if (incoming_queue_.empty())
360 : return;
361 1419 : std::swap(incoming_queue_, work_queue_);
362 1419 : DCHECK(incoming_queue_.empty());
363 : }
364 : }
365 :
366 5676 : bool MessageLoop::DeletePendingTasks() {
367 5676 : bool did_work = !work_queue_.empty();
368 11352 : while (!work_queue_.empty()) {
369 0 : PendingTask pending_task = work_queue_.front();
370 0 : work_queue_.pop();
371 0 : if (!pending_task.delayed_run_time.is_null()) {
372 : // We want to delete delayed tasks in the same order in which they would
373 : // normally be deleted in case of any funny dependencies between delayed
374 : // tasks.
375 0 : AddToDelayedWorkQueue(pending_task);
376 : } else {
377 : // TODO(darin): Delete all tasks once it is safe to do so.
378 : // Until it is totally safe, just do it when running purify.
379 : #ifdef PURIFY
380 : delete pending_task.task;
381 : #endif // PURIFY
382 : }
383 : }
384 5676 : did_work |= !deferred_non_nestable_work_queue_.empty();
385 11352 : while (!deferred_non_nestable_work_queue_.empty()) {
386 : // TODO(darin): Delete all tasks once it is safe to do so.
387 : // Until it is totaly safe, just delete them to keep purify happy.
388 : #ifdef PURIFY
389 : Task* task = deferred_non_nestable_work_queue_.front().task;
390 : #endif
391 0 : deferred_non_nestable_work_queue_.pop();
392 : #ifdef PURIFY
393 : delete task;
394 : #endif
395 : }
396 5676 : did_work |= !delayed_work_queue_.empty();
397 11352 : while (!delayed_work_queue_.empty()) {
398 0 : Task* task = delayed_work_queue_.top().task;
399 0 : delayed_work_queue_.pop();
400 0 : delete task;
401 : }
402 5676 : return did_work;
403 : }
404 :
405 4258 : bool MessageLoop::DoWork() {
406 4258 : if (!nestable_tasks_allowed_) {
407 : // Task can't be executed right now.
408 0 : return false;
409 : }
410 :
411 0 : for (;;) {
412 4258 : ReloadWorkQueue();
413 4258 : if (work_queue_.empty())
414 : break;
415 :
416 : // Execute oldest task.
417 0 : do {
418 1419 : PendingTask pending_task = work_queue_.front();
419 1419 : work_queue_.pop();
420 1419 : if (!pending_task.delayed_run_time.is_null()) {
421 0 : AddToDelayedWorkQueue(pending_task);
422 : // If we changed the topmost task, then it is time to re-schedule.
423 0 : if (delayed_work_queue_.top().task == pending_task.task)
424 0 : pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
425 : } else {
426 1419 : if (DeferOrRunPendingTask(pending_task))
427 1419 : return true;
428 : }
429 0 : } while (!work_queue_.empty());
430 : }
431 :
432 : // Nothing happened.
433 2839 : return false;
434 : }
435 :
436 4258 : bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) {
437 4258 : if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
438 4258 : *next_delayed_work_time = Time();
439 4258 : return false;
440 : }
441 :
442 0 : if (delayed_work_queue_.top().delayed_run_time > Time::Now()) {
443 0 : *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
444 0 : return false;
445 : }
446 :
447 0 : PendingTask pending_task = delayed_work_queue_.top();
448 0 : delayed_work_queue_.pop();
449 :
450 0 : if (!delayed_work_queue_.empty())
451 0 : *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
452 :
453 0 : return DeferOrRunPendingTask(pending_task);
454 : }
455 :
456 2839 : bool MessageLoop::DoIdleWork() {
457 2839 : if (ProcessNextDelayedNonNestableTask())
458 0 : return true;
459 :
460 2839 : if (state_->quit_received)
461 1419 : pump_->Quit();
462 :
463 2839 : return false;
464 : }
465 :
466 : //------------------------------------------------------------------------------
467 : // MessageLoop::AutoRunState
468 :
469 1420 : MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
470 : // Make the loop reference us.
471 1420 : previous_state_ = loop_->state_;
472 1420 : if (previous_state_) {
473 0 : run_depth = previous_state_->run_depth + 1;
474 : } else {
475 1420 : run_depth = 1;
476 : }
477 1420 : loop_->state_ = this;
478 :
479 : // Initialize the other fields:
480 1420 : quit_received = false;
481 : #if defined(OS_WIN)
482 : dispatcher = NULL;
483 : #endif
484 1420 : }
485 :
486 1419 : MessageLoop::AutoRunState::~AutoRunState() {
487 1419 : loop_->state_ = previous_state_;
488 1419 : }
489 :
490 : //------------------------------------------------------------------------------
491 : // MessageLoop::PendingTask
492 :
493 0 : bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
494 : // Since the top of a priority queue is defined as the "greatest" element, we
495 : // need to invert the comparison here. We want the smaller time to be at the
496 : // top of the heap.
497 :
498 0 : if (delayed_run_time < other.delayed_run_time)
499 0 : return false;
500 :
501 0 : if (delayed_run_time > other.delayed_run_time)
502 0 : return true;
503 :
504 : // If the times happen to match, then we use the sequence number to decide.
505 : // Compare the difference to support integer roll-over.
506 0 : return (sequence_num - other.sequence_num) > 0;
507 : }
508 :
509 : //------------------------------------------------------------------------------
510 : // MessageLoopForUI
511 :
512 : #if defined(OS_WIN)
513 :
514 : void MessageLoopForUI::Run(Dispatcher* dispatcher) {
515 : AutoRunState save_state(this);
516 : state_->dispatcher = dispatcher;
517 : RunHandler();
518 : }
519 :
520 : void MessageLoopForUI::AddObserver(Observer* observer) {
521 : pump_win()->AddObserver(observer);
522 : }
523 :
524 : void MessageLoopForUI::RemoveObserver(Observer* observer) {
525 : pump_win()->RemoveObserver(observer);
526 : }
527 :
528 : void MessageLoopForUI::WillProcessMessage(const MSG& message) {
529 : pump_win()->WillProcessMessage(message);
530 : }
531 : void MessageLoopForUI::DidProcessMessage(const MSG& message) {
532 : pump_win()->DidProcessMessage(message);
533 : }
534 : void MessageLoopForUI::PumpOutPendingPaintMessages() {
535 : pump_ui()->PumpOutPendingPaintMessages();
536 : }
537 :
538 : #endif // defined(OS_WIN)
539 :
540 : //------------------------------------------------------------------------------
541 : // MessageLoopForIO
542 :
543 : #if defined(OS_WIN)
544 :
545 : void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
546 : pump_io()->RegisterIOHandler(file, handler);
547 : }
548 :
549 : bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
550 : return pump_io()->WaitForIOCompletion(timeout, filter);
551 : }
552 :
553 : #elif defined(OS_POSIX)
554 :
555 0 : bool MessageLoopForIO::WatchFileDescriptor(int fd,
556 : bool persistent,
557 : Mode mode,
558 : FileDescriptorWatcher *controller,
559 : Watcher *delegate) {
560 : return pump_libevent()->WatchFileDescriptor(
561 : fd,
562 : persistent,
563 : static_cast<base::MessagePumpLibevent::Mode>(mode),
564 : controller,
565 0 : delegate);
566 : }
567 :
568 : bool
569 0 : MessageLoopForIO::CatchSignal(int sig,
570 : SignalEvent* sigevent,
571 : SignalWatcher* delegate)
572 : {
573 0 : return pump_libevent()->CatchSignal(sig, sigevent, delegate);
574 4392 : }
575 :
576 : #endif
|