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