| Index: base/message_loop/incoming_task_queue.cc
|
| diff --git a/base/message_loop/incoming_task_queue.cc b/base/message_loop/incoming_task_queue.cc
|
| index 2ca32d6254b6a4cfe623885e3a208f1597dbd74d..9e5b013684f003211256d011741c0cab800b0ec5 100644
|
| --- a/base/message_loop/incoming_task_queue.cc
|
| +++ b/base/message_loop/incoming_task_queue.cc
|
| @@ -6,16 +6,36 @@
|
|
|
| #include "base/location.h"
|
| #include "base/message_loop/message_loop.h"
|
| +#include "base/metrics/histogram.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/time/time.h"
|
|
|
| namespace base {
|
| namespace internal {
|
|
|
| +namespace {
|
| +
|
| +// Returns true if MessagePump::ScheduleWork() must be called one
|
| +// time for every task that is added to the MessageLoop incoming queue.
|
| +bool AlwaysNotifyPump(MessageLoop::Type type) {
|
| +#if defined(OS_ANDROID)
|
| + // The Android UI message loop needs to get notified each time a task is
|
| + // added
|
| + // to the incoming queue.
|
| + return type == MessageLoop::TYPE_UI || type == MessageLoop::TYPE_JAVA;
|
| +#else
|
| + return false;
|
| +#endif
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| IncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop)
|
| : high_res_task_count_(0),
|
| message_loop_(message_loop),
|
| - next_sequence_num_(0) {
|
| + next_sequence_num_(0),
|
| + message_loop_scheduled_(false),
|
| + always_schedule_work_(AlwaysNotifyPump(message_loop_->type())) {
|
| }
|
|
|
| bool IncomingTaskQueue::AddToIncomingQueue(
|
| @@ -56,9 +76,14 @@ int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) {
|
|
|
| // Acquire all we can from the inter-thread queue with one lock acquisition.
|
| AutoLock lock(incoming_queue_lock_);
|
| - if (!incoming_queue_.empty())
|
| + if (incoming_queue_.empty()) {
|
| + // If the loop attempts to reload but there are no tasks in the incoming
|
| + // queue, that means it will go to sleep waiting for more work. If the
|
| + // incoming queue becomes nonempty we need to schedule it again.
|
| + message_loop_scheduled_ = false;
|
| + } else {
|
| incoming_queue_.Swap(work_queue);
|
| -
|
| + }
|
| // Reset the count of high resolution tasks since our queue is now empty.
|
| int high_res_tasks = high_res_task_count_;
|
| high_res_task_count_ = 0;
|
| @@ -109,8 +134,16 @@ bool IncomingTaskQueue::PostPendingTask(PendingTask* pending_task) {
|
| incoming_queue_.push(*pending_task);
|
| pending_task->task.Reset();
|
|
|
| - // Wake up the pump.
|
| - message_loop_->ScheduleWork(was_empty);
|
| + if (always_schedule_work_ || (!message_loop_scheduled_ && was_empty)) {
|
| + // Wake up the message loop.
|
| + message_loop_->ScheduleWork();
|
| + // After we've scheduled the message loop, we do not need to do so again
|
| + // until we know it has processed all of the work in our queue and is
|
| + // waiting for more work again. The message loop will always attempt to
|
| + // reload from the incoming queue before waiting again so we clear this flag
|
| + // in ReloadWorkQueue().
|
| + message_loop_scheduled_ = true;
|
| + }
|
|
|
| return true;
|
| }
|
|
|