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