message_loop.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
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/histogram.h"
11#include "base/lazy_instance.h"
12#include "base/logging.h"
13#include "base/message_pump_default.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 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//  StartHistogrammer();
252
253#if !defined(OS_MACOSX)
254  if (state_->dispatcher && type() == TYPE_UI) {
255    static_cast<base::MessagePumpForUI*>(pump_.get())->
256        RunWithDispatcher(this, state_->dispatcher);
257    return;
258  }
259#endif
260
261  pump_->Run(this);
262}
263
264//------------------------------------------------------------------------------
265// Wrapper functions for use in above message loop framework.
266
267bool MessageLoop::ProcessNextDelayedNonNestableTask() {
268  if (state_->run_depth != 1)
269    return false;
270
271  if (deferred_non_nestable_work_queue_.empty())
272    return false;
273
274  Task* task = deferred_non_nestable_work_queue_.front().task;
275  deferred_non_nestable_work_queue_.pop();
276
277  RunTask(task);
278  return true;
279}
280
281//------------------------------------------------------------------------------
282
283void MessageLoop::Quit() {
284  DCHECK(current() == this);
285  if (state_) {
286    state_->quit_received = true;
287  } else {
288    NOTREACHED() << "Must be inside Run to call Quit";
289  }
290}
291
292void MessageLoop::QuitNow() {
293  DCHECK(current() == this);
294  if (state_) {
295    pump_->Quit();
296  } else {
297    NOTREACHED() << "Must be inside Run to call Quit";
298  }
299}
300
301void MessageLoop::PostTask(
302    const tracked_objects::Location& from_here, Task* task) {
303  PostTask_Helper(from_here, task, 0, true);
304}
305
306void MessageLoop::PostDelayedTask(
307    const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
308  PostTask_Helper(from_here, task, delay_ms, true);
309}
310
311void MessageLoop::PostNonNestableTask(
312    const tracked_objects::Location& from_here, Task* task) {
313  PostTask_Helper(from_here, task, 0, false);
314}
315
316void MessageLoop::PostNonNestableDelayedTask(
317    const tracked_objects::Location& from_here, Task* task, int64 delay_ms) {
318  PostTask_Helper(from_here, task, delay_ms, false);
319}
320
321// Possibly called on a background thread!
322void MessageLoop::PostTask_Helper(
323    const tracked_objects::Location& from_here, Task* task, int64 delay_ms,
324    bool nestable) {
325  task->SetBirthPlace(from_here);
326
327  PendingTask pending_task(task, nestable);
328
329  if (delay_ms > 0) {
330    pending_task.delayed_run_time =
331        Time::Now() + TimeDelta::FromMilliseconds(delay_ms);
332
333#if defined(OS_WIN)
334    if (high_resolution_timer_expiration_.is_null()) {
335      // Windows timers are granular to 15.6ms.  If we only set high-res
336      // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms,
337      // which as a percentage is pretty inaccurate.  So enable high
338      // res timers for any timer which is within 2x of the granularity.
339      // This is a tradeoff between accuracy and power management.
340      bool needs_high_res_timers =
341          delay_ms < (2 * Time::kMinLowResolutionThresholdMs);
342      if (needs_high_res_timers) {
343        Time::ActivateHighResolutionTimer(true);
344        high_resolution_timer_expiration_ = base::TimeTicks::Now() +
345            TimeDelta::FromMilliseconds(kHighResolutionTimerModeLeaseTimeMs);
346      }
347    }
348#endif
349  } else {
350    DCHECK_EQ(delay_ms, 0) << "delay should not be negative";
351  }
352
353#if defined(OS_WIN)
354  if (!high_resolution_timer_expiration_.is_null()) {
355    if (base::TimeTicks::Now() > high_resolution_timer_expiration_) {
356      Time::ActivateHighResolutionTimer(false);
357      high_resolution_timer_expiration_ = base::TimeTicks();
358    }
359  }
360#endif
361
362  // Warning: Don't try to short-circuit, and handle this thread's tasks more
363  // directly, as it could starve handling of foreign threads.  Put every task
364  // into this queue.
365
366  scoped_refptr<base::MessagePump> pump;
367  {
368    AutoLock locked(incoming_queue_lock_);
369
370    bool was_empty = incoming_queue_.empty();
371    incoming_queue_.push(pending_task);
372    if (!was_empty)
373      return;  // Someone else should have started the sub-pump.
374
375    pump = pump_;
376  }
377  // Since the incoming_queue_ may contain a task that destroys this message
378  // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
379  // We use a stack-based reference to the message pump so that we can call
380  // ScheduleWork outside of incoming_queue_lock_.
381
382  pump->ScheduleWork();
383}
384
385void MessageLoop::SetNestableTasksAllowed(bool allowed) {
386  if (nestable_tasks_allowed_ != allowed) {
387    nestable_tasks_allowed_ = allowed;
388    if (!nestable_tasks_allowed_)
389      return;
390    // Start the native pump if we are not already pumping.
391    pump_->ScheduleWork();
392  }
393}
394
395bool MessageLoop::NestableTasksAllowed() const {
396  return nestable_tasks_allowed_;
397}
398
399bool MessageLoop::IsNested() {
400  return state_->run_depth > 1;
401}
402
403//------------------------------------------------------------------------------
404
405void MessageLoop::RunTask(Task* task) {
406  DCHECK(nestable_tasks_allowed_);
407  // Execute the task and assume the worst: It is probably not reentrant.
408  nestable_tasks_allowed_ = false;
409
410  HistogramEvent(kTaskRunEvent);
411  FOR_EACH_OBSERVER(TaskObserver, task_observers_,
412                    WillProcessTask(task->tracked_birth_time()));
413  task->Run();
414  FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask());
415  delete task;
416
417  nestable_tasks_allowed_ = true;
418}
419
420bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
421  if (pending_task.nestable || state_->run_depth == 1) {
422    RunTask(pending_task.task);
423    // Show that we ran a task (Note: a new one might arrive as a
424    // consequence!).
425    return true;
426  }
427
428  // We couldn't run the task now because we're in a nested message loop
429  // and the task isn't nestable.
430  deferred_non_nestable_work_queue_.push(pending_task);
431  return false;
432}
433
434void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
435  // Move to the delayed work queue.  Initialize the sequence number
436  // before inserting into the delayed_work_queue_.  The sequence number
437  // is used to faciliate FIFO sorting when two tasks have the same
438  // delayed_run_time value.
439  PendingTask new_pending_task(pending_task);
440  new_pending_task.sequence_num = next_sequence_num_++;
441  delayed_work_queue_.push(new_pending_task);
442}
443
444void MessageLoop::ReloadWorkQueue() {
445  // We can improve performance of our loading tasks from incoming_queue_ to
446  // work_queue_ by waiting until the last minute (work_queue_ is empty) to
447  // load.  That reduces the number of locks-per-task significantly when our
448  // queues get large.
449  if (!work_queue_.empty())
450    return;  // Wait till we *really* need to lock and load.
451
452  // Acquire all we can from the inter-thread queue with one lock acquisition.
453  {
454    AutoLock lock(incoming_queue_lock_);
455    if (incoming_queue_.empty())
456      return;
457    incoming_queue_.Swap(&work_queue_);  // Constant time
458    DCHECK(incoming_queue_.empty());
459  }
460}
461
462bool MessageLoop::DeletePendingTasks() {
463  bool did_work = !work_queue_.empty();
464  while (!work_queue_.empty()) {
465    PendingTask pending_task = work_queue_.front();
466    work_queue_.pop();
467    if (!pending_task.delayed_run_time.is_null()) {
468      // We want to delete delayed tasks in the same order in which they would
469      // normally be deleted in case of any funny dependencies between delayed
470      // tasks.
471      AddToDelayedWorkQueue(pending_task);
472    } else {
473      // TODO(darin): Delete all tasks once it is safe to do so.
474      // Until it is totally safe, just do it when running Purify or
475      // Valgrind.
476#if defined(PURIFY)
477      delete pending_task.task;
478#elif defined(OS_POSIX)
479      if (RUNNING_ON_VALGRIND)
480        delete pending_task.task;
481#endif  // defined(OS_POSIX)
482    }
483  }
484  did_work |= !deferred_non_nestable_work_queue_.empty();
485  while (!deferred_non_nestable_work_queue_.empty()) {
486    // TODO(darin): Delete all tasks once it is safe to do so.
487    // Until it is totaly safe, only delete them under Purify and Valgrind.
488    Task* task = NULL;
489#if defined(PURIFY)
490    task = deferred_non_nestable_work_queue_.front().task;
491#elif defined(OS_POSIX)
492    if (RUNNING_ON_VALGRIND)
493      task = deferred_non_nestable_work_queue_.front().task;
494#endif
495    deferred_non_nestable_work_queue_.pop();
496    if (task)
497      delete task;
498  }
499  did_work |= !delayed_work_queue_.empty();
500  while (!delayed_work_queue_.empty()) {
501    Task* task = delayed_work_queue_.top().task;
502    delayed_work_queue_.pop();
503    delete task;
504  }
505  return did_work;
506}
507
508bool MessageLoop::DoWork() {
509  if (!nestable_tasks_allowed_) {
510    // Task can't be executed right now.
511    return false;
512  }
513
514  for (;;) {
515    ReloadWorkQueue();
516    if (work_queue_.empty())
517      break;
518
519    // Execute oldest task.
520    do {
521      PendingTask pending_task = work_queue_.front();
522      work_queue_.pop();
523      if (!pending_task.delayed_run_time.is_null()) {
524        AddToDelayedWorkQueue(pending_task);
525        // If we changed the topmost task, then it is time to re-schedule.
526        if (delayed_work_queue_.top().task == pending_task.task)
527          pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
528      } else {
529        if (DeferOrRunPendingTask(pending_task))
530          return true;
531      }
532    } while (!work_queue_.empty());
533  }
534
535  // Nothing happened.
536  return false;
537}
538
539bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) {
540  if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
541    *next_delayed_work_time = Time();
542    return false;
543  }
544
545  if (delayed_work_queue_.top().delayed_run_time > Time::Now()) {
546    *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
547    return false;
548  }
549
550  PendingTask pending_task = delayed_work_queue_.top();
551  delayed_work_queue_.pop();
552
553  if (!delayed_work_queue_.empty())
554    *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
555
556  return DeferOrRunPendingTask(pending_task);
557}
558
559bool MessageLoop::DoIdleWork() {
560  if (ProcessNextDelayedNonNestableTask())
561    return true;
562
563  if (state_->quit_received)
564    pump_->Quit();
565
566  return false;
567}
568
569//------------------------------------------------------------------------------
570// MessageLoop::AutoRunState
571
572MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
573  // Make the loop reference us.
574  previous_state_ = loop_->state_;
575  if (previous_state_) {
576    run_depth = previous_state_->run_depth + 1;
577  } else {
578    run_depth = 1;
579  }
580  loop_->state_ = this;
581
582  // Initialize the other fields:
583  quit_received = false;
584#if !defined(OS_MACOSX)
585  dispatcher = NULL;
586#endif
587}
588
589MessageLoop::AutoRunState::~AutoRunState() {
590  loop_->state_ = previous_state_;
591}
592
593//------------------------------------------------------------------------------
594// MessageLoop::PendingTask
595
596bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
597  // Since the top of a priority queue is defined as the "greatest" element, we
598  // need to invert the comparison here.  We want the smaller time to be at the
599  // top of the heap.
600
601  if (delayed_run_time < other.delayed_run_time)
602    return false;
603
604  if (delayed_run_time > other.delayed_run_time)
605    return true;
606
607  // If the times happen to match, then we use the sequence number to decide.
608  // Compare the difference to support integer roll-over.
609  return (sequence_num - other.sequence_num) > 0;
610}
611
612//------------------------------------------------------------------------------
613// Method and data for histogramming events and actions taken by each instance
614// on each thread.
615
616// static
617void MessageLoop::EnableHistogrammer(bool enable) {
618  enable_histogrammer_ = enable;
619}
620
621void MessageLoop::StartHistogrammer() {
622  if (enable_histogrammer_ && !message_histogram_.get()
623      && StatisticsRecorder::WasStarted()) {
624    DCHECK(!thread_name_.empty());
625    message_histogram_ = LinearHistogram::FactoryGet("MsgLoop:" + thread_name_,
626        kLeastNonZeroMessageId, kMaxMessageId,
627        kNumberOfDistinctMessagesDisplayed,
628        message_histogram_->kHexRangePrintingFlag);
629    message_histogram_->SetRangeDescriptions(event_descriptions_);
630  }
631}
632
633void MessageLoop::HistogramEvent(int event) {
634  if (message_histogram_.get())
635    message_histogram_->Add(event);
636}
637
638//------------------------------------------------------------------------------
639// MessageLoopForUI
640
641#if defined(OS_WIN)
642void MessageLoopForUI::DidProcessMessage(const MSG& message) {
643  pump_win()->DidProcessMessage(message);
644}
645#endif  // defined(OS_WIN)
646
647#if !defined(OS_MACOSX) && !defined(ANDROID)
648void MessageLoopForUI::AddObserver(Observer* observer) {
649  pump_ui()->AddObserver(observer);
650}
651
652void MessageLoopForUI::RemoveObserver(Observer* observer) {
653  pump_ui()->RemoveObserver(observer);
654}
655
656void MessageLoopForUI::Run(Dispatcher* dispatcher) {
657  AutoRunState save_state(this);
658  state_->dispatcher = dispatcher;
659  RunHandler();
660}
661#endif  // !defined(OS_MACOSX)
662
663//------------------------------------------------------------------------------
664// MessageLoopForIO
665
666#if defined(OS_WIN)
667
668void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
669  pump_io()->RegisterIOHandler(file, handler);
670}
671
672bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
673  return pump_io()->WaitForIOCompletion(timeout, filter);
674}
675
676#elif defined(OS_POSIX)
677
678bool MessageLoopForIO::WatchFileDescriptor(int fd,
679                                           bool persistent,
680                                           Mode mode,
681                                           FileDescriptorWatcher *controller,
682                                           Watcher *delegate) {
683  return pump_libevent()->WatchFileDescriptor(
684      fd,
685      persistent,
686      static_cast<base::MessagePumpLibevent::Mode>(mode),
687      controller,
688      delegate);
689}
690
691#endif
692