| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/message_loop/incoming_task_queue.h" | 5 #include "base/message_loop/incoming_task_queue.h" |
| 6 | 6 |
| 7 #include "base/location.h" | 7 #include "base/location.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/metrics/histogram.h" |
| 9 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
| 10 #include "base/time/time.h" | 11 #include "base/time/time.h" |
| 11 | 12 |
| 12 namespace base { | 13 namespace base { |
| 13 namespace internal { | 14 namespace internal { |
| 14 | 15 |
| 16 namespace { |
| 17 |
| 18 // Returns true if MessagePump::ScheduleWork() must be called one |
| 19 // time for every task that is added to the MessageLoop incoming queue. |
| 20 bool AlwaysNotifyPump(MessageLoop::Type type) { |
| 21 #if defined(OS_ANDROID) |
| 22 // The Android UI message loop needs to get notified each time a task is |
| 23 // added |
| 24 // to the incoming queue. |
| 25 return type == MessageLoop::TYPE_UI || type == MessageLoop::TYPE_JAVA; |
| 26 #else |
| 27 return false; |
| 28 #endif |
| 29 } |
| 30 |
| 31 } // namespace |
| 32 |
| 15 IncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop) | 33 IncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop) |
| 16 : high_res_task_count_(0), | 34 : high_res_task_count_(0), |
| 17 message_loop_(message_loop), | 35 message_loop_(message_loop), |
| 18 next_sequence_num_(0) { | 36 next_sequence_num_(0), |
| 37 message_loop_scheduled_(false), |
| 38 always_schedule_work_(AlwaysNotifyPump(message_loop_->type())) { |
| 19 } | 39 } |
| 20 | 40 |
| 21 bool IncomingTaskQueue::AddToIncomingQueue( | 41 bool IncomingTaskQueue::AddToIncomingQueue( |
| 22 const tracked_objects::Location& from_here, | 42 const tracked_objects::Location& from_here, |
| 23 const Closure& task, | 43 const Closure& task, |
| 24 TimeDelta delay, | 44 TimeDelta delay, |
| 25 bool nestable) { | 45 bool nestable) { |
| 26 AutoLock locked(incoming_queue_lock_); | 46 AutoLock locked(incoming_queue_lock_); |
| 27 PendingTask pending_task( | 47 PendingTask pending_task( |
| 28 from_here, task, CalculateDelayedRuntime(delay), nestable); | 48 from_here, task, CalculateDelayedRuntime(delay), nestable); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 49 AutoLock lock(incoming_queue_lock_); | 69 AutoLock lock(incoming_queue_lock_); |
| 50 return incoming_queue_.empty(); | 70 return incoming_queue_.empty(); |
| 51 } | 71 } |
| 52 | 72 |
| 53 int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) { | 73 int IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) { |
| 54 // Make sure no tasks are lost. | 74 // Make sure no tasks are lost. |
| 55 DCHECK(work_queue->empty()); | 75 DCHECK(work_queue->empty()); |
| 56 | 76 |
| 57 // Acquire all we can from the inter-thread queue with one lock acquisition. | 77 // Acquire all we can from the inter-thread queue with one lock acquisition. |
| 58 AutoLock lock(incoming_queue_lock_); | 78 AutoLock lock(incoming_queue_lock_); |
| 59 if (!incoming_queue_.empty()) | 79 if (incoming_queue_.empty()) { |
| 80 // If the loop attempts to reload but there are no tasks in the incoming |
| 81 // queue, that means it will go to sleep waiting for more work. If the |
| 82 // incoming queue becomes nonempty we need to schedule it again. |
| 83 message_loop_scheduled_ = false; |
| 84 } else { |
| 60 incoming_queue_.Swap(work_queue); | 85 incoming_queue_.Swap(work_queue); |
| 61 | 86 } |
| 62 // Reset the count of high resolution tasks since our queue is now empty. | 87 // Reset the count of high resolution tasks since our queue is now empty. |
| 63 int high_res_tasks = high_res_task_count_; | 88 int high_res_tasks = high_res_task_count_; |
| 64 high_res_task_count_ = 0; | 89 high_res_task_count_ = 0; |
| 65 return high_res_tasks; | 90 return high_res_tasks; |
| 66 } | 91 } |
| 67 | 92 |
| 68 void IncomingTaskQueue::WillDestroyCurrentMessageLoop() { | 93 void IncomingTaskQueue::WillDestroyCurrentMessageLoop() { |
| 69 AutoLock lock(incoming_queue_lock_); | 94 AutoLock lock(incoming_queue_lock_); |
| 70 message_loop_ = NULL; | 95 message_loop_ = NULL; |
| 71 } | 96 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 102 // delayed_run_time value) and for identifying the task in about:tracing. | 127 // delayed_run_time value) and for identifying the task in about:tracing. |
| 103 pending_task->sequence_num = next_sequence_num_++; | 128 pending_task->sequence_num = next_sequence_num_++; |
| 104 | 129 |
| 105 message_loop_->task_annotator()->DidQueueTask("MessageLoop::PostTask", | 130 message_loop_->task_annotator()->DidQueueTask("MessageLoop::PostTask", |
| 106 *pending_task); | 131 *pending_task); |
| 107 | 132 |
| 108 bool was_empty = incoming_queue_.empty(); | 133 bool was_empty = incoming_queue_.empty(); |
| 109 incoming_queue_.push(*pending_task); | 134 incoming_queue_.push(*pending_task); |
| 110 pending_task->task.Reset(); | 135 pending_task->task.Reset(); |
| 111 | 136 |
| 112 // Wake up the pump. | 137 if (always_schedule_work_ || (!message_loop_scheduled_ && was_empty)) { |
| 113 message_loop_->ScheduleWork(was_empty); | 138 // Wake up the message loop. |
| 139 message_loop_->ScheduleWork(); |
| 140 // After we've scheduled the message loop, we do not need to do so again |
| 141 // until we know it has processed all of the work in our queue and is |
| 142 // waiting for more work again. The message loop will always attempt to |
| 143 // reload from the incoming queue before waiting again so we clear this flag |
| 144 // in ReloadWorkQueue(). |
| 145 message_loop_scheduled_ = true; |
| 146 } |
| 114 | 147 |
| 115 return true; | 148 return true; |
| 116 } | 149 } |
| 117 | 150 |
| 118 } // namespace internal | 151 } // namespace internal |
| 119 } // namespace base | 152 } // namespace base |
| OLD | NEW |