ipc/chromium/src/base/message_loop.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/base/message_loop.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,593 @@
     1.4 +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +#include "base/message_loop.h"
     1.9 +
    1.10 +#include <algorithm>
    1.11 +
    1.12 +#include "mozilla/Atomics.h"
    1.13 +#include "base/compiler_specific.h"
    1.14 +#include "base/lazy_instance.h"
    1.15 +#include "base/logging.h"
    1.16 +#include "base/message_pump_default.h"
    1.17 +#include "base/string_util.h"
    1.18 +#include "base/thread_local.h"
    1.19 +
    1.20 +#if defined(OS_MACOSX)
    1.21 +#include "base/message_pump_mac.h"
    1.22 +#endif
    1.23 +#if defined(OS_POSIX)
    1.24 +#include "base/message_pump_libevent.h"
    1.25 +#endif
    1.26 +#if defined(OS_LINUX) || defined(OS_BSD)
    1.27 +#if defined(MOZ_WIDGET_GTK)
    1.28 +#include "base/message_pump_glib.h"
    1.29 +#endif
    1.30 +#ifdef MOZ_WIDGET_QT
    1.31 +#include "base/message_pump_qt.h"
    1.32 +#endif
    1.33 +#endif
    1.34 +#ifdef ANDROID
    1.35 +#include "base/message_pump_android.h"
    1.36 +#endif
    1.37 +#ifdef MOZ_TASK_TRACER
    1.38 +#include "GeckoTaskTracer.h"
    1.39 +#endif
    1.40 +
    1.41 +#include "MessagePump.h"
    1.42 +
    1.43 +using base::Time;
    1.44 +using base::TimeDelta;
    1.45 +using base::TimeTicks;
    1.46 +
    1.47 +// A lazily created thread local storage for quick access to a thread's message
    1.48 +// loop, if one exists.  This should be safe and free of static constructors.
    1.49 +static base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr(
    1.50 +    base::LINKER_INITIALIZED);
    1.51 +
    1.52 +//------------------------------------------------------------------------------
    1.53 +
    1.54 +// Logical events for Histogram profiling. Run with -message-loop-histogrammer
    1.55 +// to get an accounting of messages and actions taken on each thread.
    1.56 +static const int kTaskRunEvent = 0x1;
    1.57 +static const int kTimerEvent = 0x2;
    1.58 +
    1.59 +// Provide range of message IDs for use in histogramming and debug display.
    1.60 +static const int kLeastNonZeroMessageId = 1;
    1.61 +static const int kMaxMessageId = 1099;
    1.62 +static const int kNumberOfDistinctMessagesDisplayed = 1100;
    1.63 +
    1.64 +//------------------------------------------------------------------------------
    1.65 +
    1.66 +#if defined(OS_WIN)
    1.67 +
    1.68 +// Upon a SEH exception in this thread, it restores the original unhandled
    1.69 +// exception filter.
    1.70 +static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) {
    1.71 +  ::SetUnhandledExceptionFilter(old_filter);
    1.72 +  return EXCEPTION_CONTINUE_SEARCH;
    1.73 +}
    1.74 +
    1.75 +// Retrieves a pointer to the current unhandled exception filter. There
    1.76 +// is no standalone getter method.
    1.77 +static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
    1.78 +  LPTOP_LEVEL_EXCEPTION_FILTER top_filter = NULL;
    1.79 +  top_filter = ::SetUnhandledExceptionFilter(0);
    1.80 +  ::SetUnhandledExceptionFilter(top_filter);
    1.81 +  return top_filter;
    1.82 +}
    1.83 +
    1.84 +#endif  // defined(OS_WIN)
    1.85 +
    1.86 +//------------------------------------------------------------------------------
    1.87 +
    1.88 +// static
    1.89 +MessageLoop* MessageLoop::current() {
    1.90 +  // TODO(darin): sadly, we cannot enable this yet since people call us even
    1.91 +  // when they have no intention of using us.
    1.92 +  //DCHECK(loop) << "Ouch, did you forget to initialize me?";
    1.93 +  return lazy_tls_ptr.Pointer()->Get();
    1.94 +}
    1.95 +
    1.96 +static mozilla::Atomic<int32_t> message_loop_id_seq(0);
    1.97 +
    1.98 +MessageLoop::MessageLoop(Type type)
    1.99 +    : type_(type),
   1.100 +      id_(++message_loop_id_seq),
   1.101 +      nestable_tasks_allowed_(true),
   1.102 +      exception_restoration_(false),
   1.103 +      state_(NULL),
   1.104 +      run_depth_base_(1),
   1.105 +#ifdef OS_WIN
   1.106 +      os_modal_loop_(false),
   1.107 +#endif  // OS_WIN
   1.108 +      transient_hang_timeout_(0),
   1.109 +      permanent_hang_timeout_(0),
   1.110 +      next_sequence_num_(0) {
   1.111 +  DCHECK(!current()) << "should only have one message loop per thread";
   1.112 +  lazy_tls_ptr.Pointer()->Set(this);
   1.113 +  if (type_ == TYPE_MOZILLA_UI) {
   1.114 +    pump_ = new mozilla::ipc::MessagePump();
   1.115 +    return;
   1.116 +  }
   1.117 +  if (type_ == TYPE_MOZILLA_CHILD) {
   1.118 +    pump_ = new mozilla::ipc::MessagePumpForChildProcess();
   1.119 +    // There is a MessageLoop Run call from XRE_InitChildProcess
   1.120 +    // and another one from MessagePumpForChildProcess. The one
   1.121 +    // from MessagePumpForChildProcess becomes the base, so we need
   1.122 +    // to set run_depth_base_ to 2 or we'll never be able to process
   1.123 +    // Idle tasks.
   1.124 +    run_depth_base_ = 2;
   1.125 +    return;
   1.126 +  }
   1.127 +  if (type_ == TYPE_MOZILLA_NONMAINTHREAD) {
   1.128 +    pump_ = new mozilla::ipc::MessagePumpForNonMainThreads();
   1.129 +    return;
   1.130 +  }
   1.131 +
   1.132 +#if defined(OS_WIN)
   1.133 +  // TODO(rvargas): Get rid of the OS guards.
   1.134 +  if (type_ == TYPE_DEFAULT) {
   1.135 +    pump_ = new base::MessagePumpDefault();
   1.136 +  } else if (type_ == TYPE_IO) {
   1.137 +    pump_ = new base::MessagePumpForIO();
   1.138 +  } else {
   1.139 +    DCHECK(type_ == TYPE_UI);
   1.140 +    pump_ = new base::MessagePumpForUI();
   1.141 +  }
   1.142 +#elif defined(OS_POSIX)
   1.143 +  if (type_ == TYPE_UI) {
   1.144 +#if defined(OS_MACOSX)
   1.145 +    pump_ = base::MessagePumpMac::Create();
   1.146 +#elif defined(OS_LINUX) || defined(OS_BSD)
   1.147 +    pump_ = new base::MessagePumpForUI();
   1.148 +#endif  // OS_LINUX
   1.149 +  } else if (type_ == TYPE_IO) {
   1.150 +    pump_ = new base::MessagePumpLibevent();
   1.151 +  } else {
   1.152 +    pump_ = new base::MessagePumpDefault();
   1.153 +  }
   1.154 +#endif  // OS_POSIX
   1.155 +}
   1.156 +
   1.157 +MessageLoop::~MessageLoop() {
   1.158 +  DCHECK(this == current());
   1.159 +
   1.160 +  // Let interested parties have one last shot at accessing this.
   1.161 +  FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_,
   1.162 +                    WillDestroyCurrentMessageLoop());
   1.163 +
   1.164 +  DCHECK(!state_);
   1.165 +
   1.166 +  // Clean up any unprocessed tasks, but take care: deleting a task could
   1.167 +  // result in the addition of more tasks (e.g., via DeleteSoon).  We set a
   1.168 +  // limit on the number of times we will allow a deleted task to generate more
   1.169 +  // tasks.  Normally, we should only pass through this loop once or twice.  If
   1.170 +  // we end up hitting the loop limit, then it is probably due to one task that
   1.171 +  // is being stubborn.  Inspect the queues to see who is left.
   1.172 +  bool did_work;
   1.173 +  for (int i = 0; i < 100; ++i) {
   1.174 +    DeletePendingTasks();
   1.175 +    ReloadWorkQueue();
   1.176 +    // If we end up with empty queues, then break out of the loop.
   1.177 +    did_work = DeletePendingTasks();
   1.178 +    if (!did_work)
   1.179 +      break;
   1.180 +  }
   1.181 +  DCHECK(!did_work);
   1.182 +
   1.183 +  // OK, now make it so that no one can find us.
   1.184 +  lazy_tls_ptr.Pointer()->Set(NULL);
   1.185 +}
   1.186 +
   1.187 +void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {
   1.188 +  DCHECK(this == current());
   1.189 +  destruction_observers_.AddObserver(obs);
   1.190 +}
   1.191 +
   1.192 +void MessageLoop::RemoveDestructionObserver(DestructionObserver *obs) {
   1.193 +  DCHECK(this == current());
   1.194 +  destruction_observers_.RemoveObserver(obs);
   1.195 +}
   1.196 +
   1.197 +void MessageLoop::Run() {
   1.198 +  AutoRunState save_state(this);
   1.199 +  RunHandler();
   1.200 +}
   1.201 +
   1.202 +void MessageLoop::RunAllPending() {
   1.203 +  AutoRunState save_state(this);
   1.204 +  state_->quit_received = true;  // Means run until we would otherwise block.
   1.205 +  RunHandler();
   1.206 +}
   1.207 +
   1.208 +// Runs the loop in two different SEH modes:
   1.209 +// enable_SEH_restoration_ = false : any unhandled exception goes to the last
   1.210 +// one that calls SetUnhandledExceptionFilter().
   1.211 +// enable_SEH_restoration_ = true : any unhandled exception goes to the filter
   1.212 +// that was existed before the loop was run.
   1.213 +void MessageLoop::RunHandler() {
   1.214 +#if defined(OS_WIN)
   1.215 +  if (exception_restoration_) {
   1.216 +    LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
   1.217 +    MOZ_SEH_TRY {
   1.218 +      RunInternal();
   1.219 +    } MOZ_SEH_EXCEPT(SEHFilter(current_filter)) {
   1.220 +    }
   1.221 +    return;
   1.222 +  }
   1.223 +#endif
   1.224 +
   1.225 +  RunInternal();
   1.226 +}
   1.227 +
   1.228 +//------------------------------------------------------------------------------
   1.229 +
   1.230 +void MessageLoop::RunInternal() {
   1.231 +  DCHECK(this == current());
   1.232 +  pump_->Run(this);
   1.233 +}
   1.234 +
   1.235 +//------------------------------------------------------------------------------
   1.236 +// Wrapper functions for use in above message loop framework.
   1.237 +
   1.238 +bool MessageLoop::ProcessNextDelayedNonNestableTask() {
   1.239 +  if (state_->run_depth > run_depth_base_)
   1.240 +    return false;
   1.241 +
   1.242 +  if (deferred_non_nestable_work_queue_.empty())
   1.243 +    return false;
   1.244 +
   1.245 +  Task* task = deferred_non_nestable_work_queue_.front().task;
   1.246 +  deferred_non_nestable_work_queue_.pop();
   1.247 +
   1.248 +  RunTask(task);
   1.249 +  return true;
   1.250 +}
   1.251 +
   1.252 +//------------------------------------------------------------------------------
   1.253 +
   1.254 +void MessageLoop::Quit() {
   1.255 +  DCHECK(current() == this);
   1.256 +  if (state_) {
   1.257 +    state_->quit_received = true;
   1.258 +  } else {
   1.259 +    NOTREACHED() << "Must be inside Run to call Quit";
   1.260 +  }
   1.261 +}
   1.262 +
   1.263 +void MessageLoop::PostTask(
   1.264 +    const tracked_objects::Location& from_here, Task* task) {
   1.265 +  PostTask_Helper(from_here, task, 0, true);
   1.266 +}
   1.267 +
   1.268 +void MessageLoop::PostDelayedTask(
   1.269 +    const tracked_objects::Location& from_here, Task* task, int delay_ms) {
   1.270 +  PostTask_Helper(from_here, task, delay_ms, true);
   1.271 +}
   1.272 +
   1.273 +void MessageLoop::PostNonNestableTask(
   1.274 +    const tracked_objects::Location& from_here, Task* task) {
   1.275 +  PostTask_Helper(from_here, task, 0, false);
   1.276 +}
   1.277 +
   1.278 +void MessageLoop::PostNonNestableDelayedTask(
   1.279 +    const tracked_objects::Location& from_here, Task* task, int delay_ms) {
   1.280 +  PostTask_Helper(from_here, task, delay_ms, false);
   1.281 +}
   1.282 +
   1.283 +void MessageLoop::PostIdleTask(
   1.284 +    const tracked_objects::Location& from_here, Task* task) {
   1.285 +  DCHECK(current() == this);
   1.286 +
   1.287 +#ifdef MOZ_TASK_TRACER
   1.288 +  task = mozilla::tasktracer::CreateTracedTask(task);
   1.289 +#endif
   1.290 +
   1.291 +  task->SetBirthPlace(from_here);
   1.292 +  PendingTask pending_task(task, false);
   1.293 +  deferred_non_nestable_work_queue_.push(pending_task);
   1.294 +}
   1.295 +
   1.296 +// Possibly called on a background thread!
   1.297 +void MessageLoop::PostTask_Helper(
   1.298 +    const tracked_objects::Location& from_here, Task* task, int delay_ms,
   1.299 +    bool nestable) {
   1.300 +
   1.301 +#ifdef MOZ_TASK_TRACER
   1.302 +  task = mozilla::tasktracer::CreateTracedTask(task);
   1.303 +#endif
   1.304 +
   1.305 +  task->SetBirthPlace(from_here);
   1.306 +
   1.307 +  PendingTask pending_task(task, nestable);
   1.308 +
   1.309 +  if (delay_ms > 0) {
   1.310 +    pending_task.delayed_run_time =
   1.311 +        TimeTicks::Now() + TimeDelta::FromMilliseconds(delay_ms);
   1.312 +  } else {
   1.313 +    DCHECK(delay_ms == 0) << "delay should not be negative";
   1.314 +  }
   1.315 +
   1.316 +  // Warning: Don't try to short-circuit, and handle this thread's tasks more
   1.317 +  // directly, as it could starve handling of foreign threads.  Put every task
   1.318 +  // into this queue.
   1.319 +
   1.320 +  scoped_refptr<base::MessagePump> pump;
   1.321 +  {
   1.322 +    AutoLock locked(incoming_queue_lock_);
   1.323 +    incoming_queue_.push(pending_task);
   1.324 +    pump = pump_;
   1.325 +  }
   1.326 +  // Since the incoming_queue_ may contain a task that destroys this message
   1.327 +  // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
   1.328 +  // We use a stack-based reference to the message pump so that we can call
   1.329 +  // ScheduleWork outside of incoming_queue_lock_.
   1.330 +
   1.331 +  pump->ScheduleWork();
   1.332 +}
   1.333 +
   1.334 +void MessageLoop::SetNestableTasksAllowed(bool allowed) {
   1.335 +  if (nestable_tasks_allowed_ != allowed) {
   1.336 +    nestable_tasks_allowed_ = allowed;
   1.337 +    if (!nestable_tasks_allowed_)
   1.338 +      return;
   1.339 +    // Start the native pump if we are not already pumping.
   1.340 +    pump_->ScheduleWorkForNestedLoop();
   1.341 +  }
   1.342 +}
   1.343 +
   1.344 +void MessageLoop::ScheduleWork() {
   1.345 +  // Start the native pump if we are not already pumping.
   1.346 +  pump_->ScheduleWork();
   1.347 +}
   1.348 +
   1.349 +bool MessageLoop::NestableTasksAllowed() const {
   1.350 +  return nestable_tasks_allowed_;
   1.351 +}
   1.352 +
   1.353 +//------------------------------------------------------------------------------
   1.354 +
   1.355 +void MessageLoop::RunTask(Task* task) {
   1.356 +  DCHECK(nestable_tasks_allowed_);
   1.357 +  // Execute the task and assume the worst: It is probably not reentrant.
   1.358 +  nestable_tasks_allowed_ = false;
   1.359 +
   1.360 +  task->Run();
   1.361 +  delete task;
   1.362 +
   1.363 +  nestable_tasks_allowed_ = true;
   1.364 +}
   1.365 +
   1.366 +bool MessageLoop::DeferOrRunPendingTask(const PendingTask& pending_task) {
   1.367 +  if (pending_task.nestable || state_->run_depth <= run_depth_base_) {
   1.368 +    RunTask(pending_task.task);
   1.369 +    // Show that we ran a task (Note: a new one might arrive as a
   1.370 +    // consequence!).
   1.371 +    return true;
   1.372 +  }
   1.373 +
   1.374 +  // We couldn't run the task now because we're in a nested message loop
   1.375 +  // and the task isn't nestable.
   1.376 +  deferred_non_nestable_work_queue_.push(pending_task);
   1.377 +  return false;
   1.378 +}
   1.379 +
   1.380 +void MessageLoop::AddToDelayedWorkQueue(const PendingTask& pending_task) {
   1.381 +  // Move to the delayed work queue.  Initialize the sequence number
   1.382 +  // before inserting into the delayed_work_queue_.  The sequence number
   1.383 +  // is used to faciliate FIFO sorting when two tasks have the same
   1.384 +  // delayed_run_time value.
   1.385 +  PendingTask new_pending_task(pending_task);
   1.386 +  new_pending_task.sequence_num = next_sequence_num_++;
   1.387 +  delayed_work_queue_.push(new_pending_task);
   1.388 +}
   1.389 +
   1.390 +void MessageLoop::ReloadWorkQueue() {
   1.391 +  // We can improve performance of our loading tasks from incoming_queue_ to
   1.392 +  // work_queue_ by waiting until the last minute (work_queue_ is empty) to
   1.393 +  // load.  That reduces the number of locks-per-task significantly when our
   1.394 +  // queues get large.
   1.395 +  if (!work_queue_.empty())
   1.396 +    return;  // Wait till we *really* need to lock and load.
   1.397 +
   1.398 +  // Acquire all we can from the inter-thread queue with one lock acquisition.
   1.399 +  {
   1.400 +    AutoLock lock(incoming_queue_lock_);
   1.401 +    if (incoming_queue_.empty())
   1.402 +      return;
   1.403 +    std::swap(incoming_queue_, work_queue_);
   1.404 +    DCHECK(incoming_queue_.empty());
   1.405 +  }
   1.406 +}
   1.407 +
   1.408 +bool MessageLoop::DeletePendingTasks() {
   1.409 +  MOZ_ASSERT(work_queue_.empty());
   1.410 +  bool did_work = !deferred_non_nestable_work_queue_.empty();
   1.411 +  while (!deferred_non_nestable_work_queue_.empty()) {
   1.412 +    Task* task = deferred_non_nestable_work_queue_.front().task;
   1.413 +    deferred_non_nestable_work_queue_.pop();
   1.414 +    delete task;
   1.415 +  }
   1.416 +  did_work |= !delayed_work_queue_.empty();
   1.417 +  while (!delayed_work_queue_.empty()) {
   1.418 +    Task* task = delayed_work_queue_.top().task;
   1.419 +    delayed_work_queue_.pop();
   1.420 +    delete task;
   1.421 +  }
   1.422 +  return did_work;
   1.423 +}
   1.424 +
   1.425 +bool MessageLoop::DoWork() {
   1.426 +  if (!nestable_tasks_allowed_) {
   1.427 +    // Task can't be executed right now.
   1.428 +    return false;
   1.429 +  }
   1.430 +
   1.431 +  for (;;) {
   1.432 +    ReloadWorkQueue();
   1.433 +    if (work_queue_.empty())
   1.434 +      break;
   1.435 +
   1.436 +    // Execute oldest task.
   1.437 +    do {
   1.438 +      PendingTask pending_task = work_queue_.front();
   1.439 +      work_queue_.pop();
   1.440 +      if (!pending_task.delayed_run_time.is_null()) {
   1.441 +        AddToDelayedWorkQueue(pending_task);
   1.442 +        // If we changed the topmost task, then it is time to re-schedule.
   1.443 +        if (delayed_work_queue_.top().task == pending_task.task)
   1.444 +          pump_->ScheduleDelayedWork(pending_task.delayed_run_time);
   1.445 +      } else {
   1.446 +        if (DeferOrRunPendingTask(pending_task))
   1.447 +          return true;
   1.448 +      }
   1.449 +    } while (!work_queue_.empty());
   1.450 +  }
   1.451 +
   1.452 +  // Nothing happened.
   1.453 +  return false;
   1.454 +}
   1.455 +
   1.456 +bool MessageLoop::DoDelayedWork(TimeTicks* next_delayed_work_time) {
   1.457 +  if (!nestable_tasks_allowed_ || delayed_work_queue_.empty()) {
   1.458 +    *next_delayed_work_time = TimeTicks();
   1.459 +    return false;
   1.460 +  }
   1.461 +
   1.462 +  if (delayed_work_queue_.top().delayed_run_time > TimeTicks::Now()) {
   1.463 +    *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
   1.464 +    return false;
   1.465 +  }
   1.466 +
   1.467 +  PendingTask pending_task = delayed_work_queue_.top();
   1.468 +  delayed_work_queue_.pop();
   1.469 +
   1.470 +  if (!delayed_work_queue_.empty())
   1.471 +    *next_delayed_work_time = delayed_work_queue_.top().delayed_run_time;
   1.472 +
   1.473 +  return DeferOrRunPendingTask(pending_task);
   1.474 +}
   1.475 +
   1.476 +bool MessageLoop::DoIdleWork() {
   1.477 +  if (ProcessNextDelayedNonNestableTask())
   1.478 +    return true;
   1.479 +
   1.480 +  if (state_->quit_received)
   1.481 +    pump_->Quit();
   1.482 +
   1.483 +  return false;
   1.484 +}
   1.485 +
   1.486 +//------------------------------------------------------------------------------
   1.487 +// MessageLoop::AutoRunState
   1.488 +
   1.489 +MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
   1.490 +  // Make the loop reference us.
   1.491 +  previous_state_ = loop_->state_;
   1.492 +  if (previous_state_) {
   1.493 +    run_depth = previous_state_->run_depth + 1;
   1.494 +  } else {
   1.495 +    run_depth = 1;
   1.496 +  }
   1.497 +  loop_->state_ = this;
   1.498 +
   1.499 +  // Initialize the other fields:
   1.500 +  quit_received = false;
   1.501 +#if defined(OS_WIN)
   1.502 +  dispatcher = NULL;
   1.503 +#endif
   1.504 +}
   1.505 +
   1.506 +MessageLoop::AutoRunState::~AutoRunState() {
   1.507 +  loop_->state_ = previous_state_;
   1.508 +}
   1.509 +
   1.510 +//------------------------------------------------------------------------------
   1.511 +// MessageLoop::PendingTask
   1.512 +
   1.513 +bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
   1.514 +  // Since the top of a priority queue is defined as the "greatest" element, we
   1.515 +  // need to invert the comparison here.  We want the smaller time to be at the
   1.516 +  // top of the heap.
   1.517 +
   1.518 +  if (delayed_run_time < other.delayed_run_time)
   1.519 +    return false;
   1.520 +
   1.521 +  if (delayed_run_time > other.delayed_run_time)
   1.522 +    return true;
   1.523 +
   1.524 +  // If the times happen to match, then we use the sequence number to decide.
   1.525 +  // Compare the difference to support integer roll-over.
   1.526 +  return (sequence_num - other.sequence_num) > 0;
   1.527 +}
   1.528 +
   1.529 +//------------------------------------------------------------------------------
   1.530 +// MessageLoopForUI
   1.531 +
   1.532 +#if defined(OS_WIN)
   1.533 +
   1.534 +void MessageLoopForUI::Run(Dispatcher* dispatcher) {
   1.535 +  AutoRunState save_state(this);
   1.536 +  state_->dispatcher = dispatcher;
   1.537 +  RunHandler();
   1.538 +}
   1.539 +
   1.540 +void MessageLoopForUI::AddObserver(Observer* observer) {
   1.541 +  pump_win()->AddObserver(observer);
   1.542 +}
   1.543 +
   1.544 +void MessageLoopForUI::RemoveObserver(Observer* observer) {
   1.545 +  pump_win()->RemoveObserver(observer);
   1.546 +}
   1.547 +
   1.548 +void MessageLoopForUI::WillProcessMessage(const MSG& message) {
   1.549 +  pump_win()->WillProcessMessage(message);
   1.550 +}
   1.551 +void MessageLoopForUI::DidProcessMessage(const MSG& message) {
   1.552 +  pump_win()->DidProcessMessage(message);
   1.553 +}
   1.554 +void MessageLoopForUI::PumpOutPendingPaintMessages() {
   1.555 +  pump_ui()->PumpOutPendingPaintMessages();
   1.556 +}
   1.557 +
   1.558 +#endif  // defined(OS_WIN)
   1.559 +
   1.560 +//------------------------------------------------------------------------------
   1.561 +// MessageLoopForIO
   1.562 +
   1.563 +#if defined(OS_WIN)
   1.564 +
   1.565 +void MessageLoopForIO::RegisterIOHandler(HANDLE file, IOHandler* handler) {
   1.566 +  pump_io()->RegisterIOHandler(file, handler);
   1.567 +}
   1.568 +
   1.569 +bool MessageLoopForIO::WaitForIOCompletion(DWORD timeout, IOHandler* filter) {
   1.570 +  return pump_io()->WaitForIOCompletion(timeout, filter);
   1.571 +}
   1.572 +
   1.573 +#elif defined(OS_POSIX)
   1.574 +
   1.575 +bool MessageLoopForIO::WatchFileDescriptor(int fd,
   1.576 +                                           bool persistent,
   1.577 +                                           Mode mode,
   1.578 +                                           FileDescriptorWatcher *controller,
   1.579 +                                           Watcher *delegate) {
   1.580 +  return pump_libevent()->WatchFileDescriptor(
   1.581 +      fd,
   1.582 +      persistent,
   1.583 +      static_cast<base::MessagePumpLibevent::Mode>(mode),
   1.584 +      controller,
   1.585 +      delegate);
   1.586 +}
   1.587 +
   1.588 +bool
   1.589 +MessageLoopForIO::CatchSignal(int sig,
   1.590 +                              SignalEvent* sigevent,
   1.591 +                              SignalWatcher* delegate)
   1.592 +{
   1.593 +  return pump_libevent()->CatchSignal(sig, sigevent, delegate);
   1.594 +}
   1.595 +
   1.596 +#endif

mercurial