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