message_loop.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1// Copyright (c) 2010 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/metrics/histogram.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#include "base/third_party/valgrind/valgrind.h"
22#endif
23#if defined(OS_POSIX) && !defined(OS_MACOSX)
24#include "base/message_pump_glib.h"
25#endif
26
27using base::Time;
28using base::TimeDelta;
29
30namespace {
31
32// A lazily created thread local storage for quick access to a thread's message
33// loop, if one exists.  This should be safe and free of static constructors.
34base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr(
35    base::LINKER_INITIALIZED);
36
37// Logical events for Histogram profiling. Run with -message-loop-histogrammer
38// to get an accounting of messages and actions taken on each thread.
39const int kTaskRunEvent = 0x1;
40const int kTimerEvent = 0x2;
41
42// Provide range of message IDs for use in histogramming and debug display.
43const int kLeastNonZeroMessageId = 1;
44const int kMaxMessageId = 1099;
45const int kNumberOfDistinctMessagesDisplayed = 1100;
46
47// Provide a macro that takes an expression (such as a constant, or macro
48// constant) and creates a pair to initalize an array of pairs.  In this case,
49// our pair consists of the expressions value, and the "stringized" version
50// of the expression (i.e., the exrpression put in quotes).  For example, if
51// we have:
52//    #define FOO 2
53//    #define BAR 5
54// then the following:
55//    VALUE_TO_NUMBER_AND_NAME(FOO + BAR)
56// will expand to:
57//   {7, "FOO + BAR"}
58// We use the resulting array as an argument to our histogram, which reads the
59// number as a bucket identifier, and proceeds to use the corresponding name
60// in the pair (i.e., the quoted string) when printing out a histogram.
61#define VALUE_TO_NUMBER_AND_NAME(name) {name, #name},
62
63const base::LinearHistogram::DescriptionPair event_descriptions_[] = {
64  // Provide some pretty print capability in our histogram for our internal
65  // messages.
66
67  // A few events we handle (kindred to messages), and used to profile actions.
68  VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent)
69  VALUE_TO_NUMBER_AND_NAME(kTimerEvent)
70
71  {-1, NULL}  // The list must be null terminated, per API to histogram.
72};
73
74bool enable_histogrammer_ = false;
75
76}  // namespace
77
78//------------------------------------------------------------------------------
79
80#if defined(OS_WIN)
81
82// Upon a SEH exception in this thread, it restores the original unhandled
83// exception filter.
84static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) {
85  ::SetUnhandledExceptionFilter(old_filter);
86  return EXCEPTION_CONTINUE_SEARCH;
87}
88
89// Retrieves a pointer to the current unhandled exception filter. There
90// is no standalone getter method.
91static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
92  LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL;
93  top_filter = ::SetUnhandledExceptionFilter(0);
94  ::SetUnhandledExceptionFilter(top_filter);
95  return top_filter;
96}
97
98#endif  // defined(OS_WIN)
99
100//------------------------------------------------------------------------------
101
102MessageLoop::TaskObserver::TaskObserver() {
103}
104
105MessageLoop::TaskObserver::~TaskObserver() {
106}
107
108MessageLoop::DestructionObserver::~DestructionObserver() {
109}
110
111//------------------------------------------------------------------------------
112
113// static
114MessageLoop* MessageLoop::current() {
115  // TODO(darin): sadly, we cannot enable this yet since people call us even
116  // when they have no intention of using us.
117  // DCHECK(loop) << "Ouch, did you forget to initialize me?";
118  return lazy_tls_ptr.Pointer()->Get();
119}
120
121MessageLoop::MessageLoop(Type type)
122    : type_(type),
123      nestable_tasks_allowed_(true),
124      exception_restoration_(false),
125      state_(NULL),
126      next_sequence_num_(0) {
127  DCHECK(!current()) << "should only have one message loop per thread";
128  lazy_tls_ptr.Pointer()->Set(this);
129
130// TODO(rvargas): Get rid of the OS guards.
131#if defined(OS_WIN)
132#define MESSAGE_PUMP_UI new base::MessagePumpForUI()
133#define MESSAGE_PUMP_IO new base::MessagePumpForIO()
134#elif defined(OS_MACOSX)
135#define MESSAGE_PUMP_UI base::MessagePumpMac::Create()
136#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
137#elif defined(ANDROID)
138#define MESSAGE_PUMP_UI new base::MessagePumpDefault()
139#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
140#elif defined(OS_POSIX)  // POSIX but not MACOSX.
141#define MESSAGE_PUMP_UI new base::MessagePumpForUI()
142#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
143#else
144#error Not implemented
145#endif
146
147  if (type_ == TYPE_UI) {
148    pump_ = MESSAGE_PUMP_UI;
149  } else if (type_ == TYPE_IO) {
150    pump_ = MESSAGE_PUMP_IO;
151  } else {
152    DCHECK_EQ(TYPE_DEFAULT, type_);
153    pump_ = new base::MessagePumpDefault();
154  }
155}
156
157MessageLoop::~MessageLoop() {
158  DCHECK(this == current());
159
160  // Let interested parties have one last shot at accessing this.
161  FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
162                    WillDestroyCurrentMessageLoop());
163
164  DCHECK(!state_);
165
166  // Clean up any unprocessed tasks, but take care: deleting a task could
167  // result in the addition of more tasks (e.g., via DeleteSoon).  We set a
168  // limit on the number of times we will allow a deleted task to generate more
169  // tasks.  Normally, we should only pass through this loop once or twice.  If
170  // we end up hitting the loop limit, then it is probably due to one task that
171  // is being stubborn.  Inspect the queues to see who is left.
172  bool did_work;
173  for (int i = 0; i < 100; ++i) {
174    DeletePendingTasks();
175    ReloadWorkQueue();
176    // If we end up with empty queues, then break out of the loop.
177    did_work = DeletePendingTasks();
178    if (!did_work)
179      break;
180  }
181  DCHECK(!did_work);
182
183  // OK, now make it so that no one can find us.
184  lazy_tls_ptr.Pointer()->Set(NULL);
185}
186
187void MessageLoop::AddDestructionObserver(
188    DestructionObserver* destruction_observer) {
189  DCHECK(this == current());
190  destruction_observers_.AddObserver(destruction_observer);
191}
192
193void MessageLoop::RemoveDestructionObserver(
194    DestructionObserver* destruction_observer) {
195  DCHECK(this == current());
196  destruction_observers_.RemoveObserver(destruction_observer);
197}
198
199void MessageLoop::AddTaskObserver(TaskObserver* task_observer) {
200  DCHECK_EQ(this, current());
201  task_observers_.AddObserver(task_observer);
202}
203
204void MessageLoop::RemoveTaskObserver(TaskObserver* task_observer) {
205  DCHECK_EQ(this, current());
206  task_observers_.RemoveObserver(task_observer);
207}
208
209void MessageLoop::Run() {
210  AutoRunState save_state(this);
211  RunHandler();
212}
213
214void MessageLoop::RunAllPending() {
215  AutoRunState save_state(this);
216  state_->quit_received = true;  // Means run until we would otherwise block.
217  RunHandler();
218}
219
220// Runs the loop in two different SEH modes:
221// enable_SEH_restoration_ = false : any unhandled exception goes to the last
222// one that calls SetUnhandledExceptionFilter().
223// enable_SEH_restoration_ = true : any unhandled exception goes to the filter
224// that was existed before the loop was run.
225void MessageLoop::RunHandler() {
226#if defined(OS_WIN)
227  if (exception_restoration_) {
228    RunInternalInSEHFrame();
229    return;
230  }
231#endif
232
233  RunInternal();
234}
235//------------------------------------------------------------------------------
236#if defined(OS_WIN)
237__declspec(noinline) void MessageLoop::RunInternalInSEHFrame() {
238  LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
239  __try {
240    RunInternal();
241  } __except(SEHFilter(current_filter)) {
242  }
243  return;
244}
245#endif
246//------------------------------------------------------------------------------
247
248void MessageLoop::RunInternal() {
249  DCHECK(this == current());
250
251#ifndef ANDROID
252  StartHistogrammer();
253#endif
254
255#if !defined(OS_MACOSX)
256  if (state_->dispatcher && type() == TYPE_UI) {
257    static_cast<base::MessagePumpForUI*>(pump_.get())->
258        RunWithDispatcher(this, state_->dispatcher);
259    return;
260  }
261#endif
262
263  pump_->Run(this);
264}
265
266//------------------------------------------------------------------------------
267// Wrapper functions for use in above message loop framework.
268
269bool MessageLoop::ProcessNextDelayedNonNestableTask() {
270  if (state_->run_depth != 1)
271    return false;
272
273  if (deferred_non_nestable_work_queue_.empty())
274    return false;
275
276  Task* task = deferred_non_nestable_work_queue_.front().task;
277  deferred_non_nestable_work_queue_.pop();
278
279  RunTask(task);
280  return true;
281}
282
283//------------------------------------------------------------------------------
284
285void MessageLoop::Quit() {
286  DCHECK(current() == this);
287  if (state_) {
288    state_->quit_received = true;
289  } else {
290    NOTREACHED() << "Must be inside Run to call Quit";
291  }
292}
293
294void MessageLoop::QuitNow() {
295  DCHECK(current() == this);
296  if (state_) {
297    pump_->Quit();
298  } else {
299    NOTREACHED() << "Must be inside Run to call Quit";
300  }
301}
302
303void MessageLoop::PostTask(
304    const tracked_objects::Location& from_here, Task* task) {
305  PostTask_Helper(from_here, task, 0, true);
306}
307
308void MessageLoop::PostDelayedTask(
309    const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
310  PostTask_Helper(from_here, task, delay_ms, true);
311}
312
313void MessageLoop::PostNonNestableTask(
314    const tracked_objects::Location& from_here, Task* task) {
315  PostTask_Helper(from_here, task, 0, false);
316}
317
318void MessageLoop::PostNonNestableDelayedTask(
319    const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
320  PostTask_Helper(from_here, task, delay_ms, false);
321}
322
323// Possibly called on a background thread!
324void MessageLoop::PostTask_Helper(
325    const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
326    bool nestable) {
327  task->SetBirthPlace(from_here);
328
329  PendingTask pending_task(task, nestable);
330
331  if (delay_ms > 0) {
332    pending_task.delayed_run_time =
333        Time::Now() + TimeDelta::FromMilliseconds(delay_ms);
334
335#if defined(OS_WIN)
336    if (high_resolution_timer_expiration_.is_null()) {
337      // Windows timers are granular to 15.6ms.  If we only set high-res
338      // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms,
339      // which as a percentage is pretty inaccurate.  So enable high
340      // res timers for any timer which is within 2x of the granularity.
341      // This is a tradeoff between accuracy and power management.
342      bool needs_high_res_timers =
343          delay_ms < (2 * Time::kMinLowResolutionThresholdMs);
344      if (needs_high_res_timers) {
345        Time::ActivateHighResolutionTimer(true);
346        high_resolution_timer_expiration_ = base::TimeTicks::Now() +
347            TimeDelta::FromMilliseconds(kHighResolutionTimerModeLeaseTimeMs);
348      }
349    }
350#endif
351  } else {
352    DCHECK_EQ(delay_ms, 0) << "delay should not be negative";
353  }
354
355#if defined(OS_WIN)
356  if (!high_resolution_timer_expiration_.is_null()) {
357    if (base::TimeTicks::Now() > high_resolution_timer_expiration_) {
358      Time::ActivateHighResolutionTimer(false);
359      high_resolution_timer_expiration_ = base::TimeTicks();
360    }
361  }
362#endif
363
364  // Warning: Don't try to short-circuit, and handle this thread's tasks more
365  // directly, as it could starve handling of foreign threads.  Put every task
366  // into this queue.
367
368  scoped_refptr<base::MessagePump> pump;
369  {
370    AutoLock locked(incoming_queue_lock_);
371
372    bool was_empty = incoming_queue_.empty();
373    incoming_queue_.push(pending_task);
374    if (!was_empty)
375      return;  // Someone else should have started the sub-pump.
376
377    pump = pump_;
378  }
379  // Since the incoming_queue_ may contain a task that destroys this message
380  // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
381  // We use a stack-based reference to the message pump so that we can call
382  // ScheduleWork outside of incoming_queue_lock_.
383
384  pump->ScheduleWork();
385}
386
387void MessageLoop::SetNestableTasksAllowed(bool allowed) {
388  if (nestable_tasks_allowed_ != allowed) {
389    nestable_tasks_allowed_ = allowed;
390    if (!nestable_tasks_allowed_)
391      return;
392    // Start the native pump if we are not already pumping.
393    pump_->ScheduleWork();
394  }
395}
396
397bool MessageLoop::NestableTasksAllowed() const {
398  return nestable_tasks_allowed_;
399}
400
401bool MessageLoop::IsNested() {
402  return state_->run_depth > 1;
403}
404
405//------------------------------------------------------------------------------
406
407void MessageLoop::RunTask(Task* task) {
408  DCHECK(nestable_tasks_allowed_);
409  // Execute the task and assume the worst: It is probably not reentrant.
410  nestable_tasks_allowed_ = false;
411
412  HistogramEvent(kTaskRunEvent);
413  FOR_EACH_OBSERVER(TaskObserver, task_observers_,
414                    WillProcessTask(task->tracked_birth_time()));
415  task->Run();
416  FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask());
417  delete task;
418
419  nestable_tasks_allowed_ = true;
420}
421
422bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
423  if (pending_task.nestable || state_->run_depth == 1) {
424    RunTask(pending_task.task);
425    // Show that we ran a task (Note: a new one might arrive as a
426    // consequence!).
427    return true;
428  }
429
430  // We couldn't run the task now because we're in a nested message loop
431  // and the task isn't nestable.
432  deferred_non_nestable_work_queue_.push(pending_task);
433  return false;
434}
435
436void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
437  // Move to the delayed work queue.  Initialize the sequence number
438  // before inserting into the delayed_work_queue_.  The sequence number
439  // is used to faciliate FIFO sorting when two tasks have the same
440  // delayed_run_time value.
441  PendingTask new_pending_task(pending_task);
442  new_pending_task.sequence_num = next_sequence_num_++;
443  delayed_work_queue_.push(new_pending_task);
444}
445
446void MessageLoop::ReloadWorkQueue() {
447  // We can improve performance of our loading tasks from incoming_queue_ to
448  // work_queue_ by waiting until the last minute (work_queue_ is empty) to
449  // load.  That reduces the number of locks-per-task significantly when our
450  // queues get large.
451  if (!work_queue_.empty())
452    return;  // Wait till we *really* need to lock and load.
453
454  // Acquire all we can from the inter-thread queue with one lock acquisition.
455  {
456    AutoLock lock(incoming_queue_lock_);
457    if (incoming_queue_.empty())
458      return;
459    incoming_queue_.Swap(&work_queue_);  // Constant time
460    DCHECK(incoming_queue_.empty());
461  }
462}
463
464bool MessageLoop::DeletePendingTasks() {
465  bool did_work = !work_queue_.empty();
466  while (!work_queue_.empty()) {
467    PendingTask pending_task = work_queue_.front();
468    work_queue_.pop();
469    if (!pending_task.delayed_run_time.is_null()) {
470      // We want to delete delayed tasks in the same order in which they would
471      // normally be deleted in case of any funny dependencies between delayed
472      // tasks.
473      AddToDelayedWorkQueue(pending_task);
474    } else {
475      // TODO(darin): Delete all tasks once it is safe to do so.
476      // Until it is totally safe, just do it when running Purify or
477      // Valgrind.
478#if defined(PURIFY)
479      delete pending_task.task;
480#elif defined(OS_POSIX)
481      if (RUNNING_ON_VALGRIND)
482        delete pending_task.task;
483#endif  // defined(OS_POSIX)
484    }
485  }
486  did_work |= !deferred_non_nestable_work_queue_.empty();
487  while (!deferred_non_nestable_work_queue_.empty()) {
488    // TODO(darin): Delete all tasks once it is safe to do so.
489    // Until it is totaly safe, only delete them under Purify and Valgrind.
490    Task* task = NULL;
491#if defined(PURIFY)
492    task = deferred_non_nestable_work_queue_.front().task;
493#elif defined(OS_POSIX)
494    if (RUNNING_ON_VALGRIND)
495      task = deferred_non_nestable_work_queue_.front().task;
496#endif
497    deferred_non_nestable_work_queue_.pop();
498    if (task)
499      delete task;
500  }
501  did_work |= !delayed_work_queue_.empty();
502  while (!delayed_work_queue_.empty()) {
503    Task* task = delayed_work_queue_.top().task;
504    delayed_work_queue_.pop();
505    delete task;
506  }
507  return did_work;
508}
509
510bool MessageLoop::DoWork() {
511  if (!nestable_tasks_allowed_) {
512    // Task can't be executed right now.
513    return false;
514  }
515
516  for (;;) {
517    ReloadWorkQueue();
518    if (work_queue_.empty())
519      break;
520
521    // Execute oldest task.
522    do {
523      PendingTask pending_task = work_queue_.front();
524      work_queue_.pop();
525      if (!pending_task.delayed_run_time.is_null()) {
526        AddToDelayedWorkQueue(pending_task);
527        // If we changed the topmost task, then it is time to re-schedule.
528        if (delayed_work_queue_.top().task == pending_task.task)
529          pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
530      } else {
531        if (DeferOrRunPendingTask(pending_task))
532          return true;
533      }
534    } while (!work_queue_.empty());
535  }
536
537  // Nothing happened.
538  return false;
539}
540
541bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) {
542  if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
543    *next_delayed_work_time = Time();
544    return false;
545  }
546
547  if (delayed_work_queue_.top().delayed_run_time > Time::Now()) {
548    *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
549    return false;
550  }
551
552  PendingTask pending_task = delayed_work_queue_.top();
553  delayed_work_queue_.pop();
554
555  if (!delayed_work_queue_.empty())
556    *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
557
558  return DeferOrRunPendingTask(pending_task);
559}
560
561bool MessageLoop::DoIdleWork() {
562  if (ProcessNextDelayedNonNestableTask())
563    return true;
564
565  if (state_->quit_received)
566    pump_->Quit();
567
568  return false;
569}
570
571//------------------------------------------------------------------------------
572// MessageLoop::AutoRunState
573
574MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
575  // Make the loop reference us.
576  previous_state_ = loop_->state_;
577  if (previous_state_) {
578    run_depth = previous_state_->run_depth + 1;
579  } else {
580    run_depth = 1;
581  }
582  loop_->state_ = this;
583
584  // Initialize the other fields:
585  quit_received = false;
586#if !defined(OS_MACOSX)
587  dispatcher = NULL;
588#endif
589}
590
591MessageLoop::AutoRunState::~AutoRunState() {
592  loop_->state_ = previous_state_;
593}
594
595//------------------------------------------------------------------------------
596// MessageLoop::PendingTask
597
598bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
599  // Since the top of a priority queue is defined as the "greatest" element, we
600  // need to invert the comparison here.  We want the smaller time to be at the
601  // top of the heap.
602
603  if (delayed_run_time < other.delayed_run_time)
604    return false;
605
606  if (delayed_run_time > other.delayed_run_time)
607    return true;
608
609  // If the times happen to match, then we use the sequence number to decide.
610  // Compare the difference to support integer roll-over.
611  return (sequence_num - other.sequence_num) > 0;
612}
613
614//------------------------------------------------------------------------------
615// Method and data for histogramming events and actions taken by each instance
616// on each thread.
617
618// static
619void MessageLoop::EnableHistogrammer(bool enable) {
620  enable_histogrammer_ = enable;
621}
622
623void MessageLoop::StartHistogrammer() {
624  if (enable_histogrammer_ && !message_histogram_.get()
625      && base::StatisticsRecorder::WasStarted()) {
626    DCHECK(!thread_name_.empty());
627    message_histogram_ = base::LinearHistogram::FactoryGet(
628        "MsgLoop:" + thread_name_,
629        kLeastNonZeroMessageId, kMaxMessageId,
630        kNumberOfDistinctMessagesDisplayed,
631        message_histogram_->kHexRangePrintingFlag);
632    message_histogram_->SetRangeDescriptions(event_descriptions_);
633  }
634}
635
636void MessageLoop::HistogramEvent(int event) {
637  if (message_histogram_.get())
638    message_histogram_->Add(event);
639}
640
641//------------------------------------------------------------------------------
642// MessageLoopForUI
643
644#if defined(OS_WIN)
645void MessageLoopForUI::DidProcessMessage(const MSG& message) {
646  pump_win()->DidProcessMessage(message);
647}
648#endif  // defined(OS_WIN)
649
650#if !defined(OS_MACOSX) && !defined(ANDROID)
651void MessageLoopForUI::AddObserver(Observer* observer) {
652  pump_ui()->AddObserver(observer);
653}
654
655void MessageLoopForUI::RemoveObserver(Observer* observer) {
656  pump_ui()->RemoveObserver(observer);
657}
658
659void MessageLoopForUI::Run(Dispatcher* dispatcher) {
660  AutoRunState save_state(this);
661  state_->dispatcher = dispatcher;
662  RunHandler();
663}
664#endif  // !defined(OS_MACOSX)
665
666//------------------------------------------------------------------------------
667// MessageLoopForIO
668
669#if defined(OS_WIN)
670
671void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
672  pump_io()->RegisterIOHandler(file, handler);
673}
674
675bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
676  return pump_io()->WaitForIOCompletion(timeout, filter);
677}
678
679#elif defined(OS_POSIX)
680
681bool MessageLoopForIO::WatchFileDescriptor(int fd,
682                                           bool persistent,
683                                           Mode mode,
684                                           FileDescriptorWatcher *controller,
685                                           Watcher *delegate) {
686  return pump_libevent()->WatchFileDescriptor(
687      fd,
688      persistent,
689      static_cast<base::MessagePumpLibevent::Mode>(mode),
690      controller,
691      delegate);
692}
693
694#endif
695