OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/scheduler/child/task_queue_manager.h" | 5 #include "components/scheduler/child/task_queue_manager.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 } | 97 } |
98 | 98 |
99 void TaskQueueManager::UnregisterAsUpdatableTaskQueue( | 99 void TaskQueueManager::UnregisterAsUpdatableTaskQueue( |
100 internal::TaskQueueImpl* queue) { | 100 internal::TaskQueueImpl* queue) { |
101 DCHECK(main_thread_checker_.CalledOnValidThread()); | 101 DCHECK(main_thread_checker_.CalledOnValidThread()); |
102 updatable_queue_set_.erase(queue); | 102 updatable_queue_set_.erase(queue); |
103 } | 103 } |
104 | 104 |
105 void TaskQueueManager::UpdateWorkQueues( | 105 void TaskQueueManager::UpdateWorkQueues( |
106 bool should_trigger_wakeup, | 106 bool should_trigger_wakeup, |
107 const internal::TaskQueueImpl::Task* previous_task) { | 107 const base::PendingTask* previous_task) { |
108 DCHECK(main_thread_checker_.CalledOnValidThread()); | 108 DCHECK(main_thread_checker_.CalledOnValidThread()); |
109 internal::LazyNow lazy_now(this); | 109 internal::LazyNow lazy_now(this); |
110 | 110 |
111 // Insert any newly updatable queues into the updatable_queue_set_. | 111 // Insert any newly updatable queues into the updatable_queue_set_. |
112 { | 112 { |
113 base::AutoLock lock(newly_updatable_lock_); | 113 base::AutoLock lock(newly_updatable_lock_); |
114 while (!newly_updatable_.empty()) { | 114 while (!newly_updatable_.empty()) { |
115 updatable_queue_set_.insert(newly_updatable_.back()); | 115 updatable_queue_set_.insert(newly_updatable_.back()); |
116 newly_updatable_.pop_back(); | 116 newly_updatable_.pop_back(); |
117 } | 117 } |
118 } | 118 } |
119 | 119 |
120 auto iter = updatable_queue_set_.begin(); | 120 auto iter = updatable_queue_set_.begin(); |
121 while (iter != updatable_queue_set_.end()) { | 121 while (iter != updatable_queue_set_.end()) { |
122 internal::TaskQueueImpl* queue = *iter++; | 122 internal::TaskQueueImpl* queue = *iter++; |
123 // NOTE Update work queue may erase itself from |updatable_queue_set_|. | 123 // NOTE Update work queue may erase itself from |updatable_queue_set_|. |
124 // This is fine, erasing an element won't invalidate any interator, as long | 124 // This is fine, erasing an element won't invalidate any interator, as long |
125 // as the iterator isn't the element being delated. | 125 // as the iterator isn't the element being delated. |
126 if (queue->work_queue().empty()) | 126 if (queue->work_queue().empty()) |
127 queue->UpdateWorkQueue(&lazy_now, should_trigger_wakeup, previous_task); | 127 queue->UpdateWorkQueue(&lazy_now, should_trigger_wakeup, previous_task); |
| 128 if (!queue->work_queue().empty()) { |
| 129 // Currently we should not be getting tasks with delayed run times in any |
| 130 // of the work queues. |
| 131 DCHECK(queue->work_queue().front().delayed_run_time.is_null()); |
| 132 } |
128 } | 133 } |
129 } | 134 } |
130 | 135 |
131 void TaskQueueManager::MaybePostDoWorkOnMainRunner() { | 136 void TaskQueueManager::MaybePostDoWorkOnMainRunner() { |
132 bool on_main_thread = main_task_runner_->BelongsToCurrentThread(); | 137 bool on_main_thread = main_task_runner_->BelongsToCurrentThread(); |
133 if (on_main_thread) { | 138 if (on_main_thread) { |
134 // We only want one pending DoWork posted from the main thread, or we risk | 139 // We only want one pending DoWork posted from the main thread, or we risk |
135 // an explosion of pending DoWorks which could starve out everything else. | 140 // an explosion of pending DoWorks which could starve out everything else. |
136 if (pending_dowork_count_ > 0) { | 141 if (pending_dowork_count_ > 0) { |
137 return; | 142 return; |
138 } | 143 } |
139 pending_dowork_count_++; | 144 pending_dowork_count_++; |
140 main_task_runner_->PostTask(FROM_HERE, do_work_from_main_thread_closure_); | 145 main_task_runner_->PostTask(FROM_HERE, do_work_from_main_thread_closure_); |
141 } else { | 146 } else { |
142 main_task_runner_->PostTask(FROM_HERE, do_work_from_other_thread_closure_); | 147 main_task_runner_->PostTask(FROM_HERE, do_work_from_other_thread_closure_); |
143 } | 148 } |
144 } | 149 } |
145 | 150 |
146 void TaskQueueManager::DoWork(bool posted_from_main_thread) { | 151 void TaskQueueManager::DoWork(bool posted_from_main_thread) { |
147 if (posted_from_main_thread) { | 152 if (posted_from_main_thread) { |
148 pending_dowork_count_--; | 153 pending_dowork_count_--; |
149 DCHECK_GE(pending_dowork_count_, 0); | 154 DCHECK_GE(pending_dowork_count_, 0); |
150 } | 155 } |
151 DCHECK(main_thread_checker_.CalledOnValidThread()); | 156 DCHECK(main_thread_checker_.CalledOnValidThread()); |
152 | 157 |
153 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a | 158 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a |
154 // pump-after-wakeup queue. | 159 // pump-after-wakeup queue. |
155 UpdateWorkQueues(false, nullptr); | 160 UpdateWorkQueues(false, nullptr); |
156 | 161 |
157 internal::TaskQueueImpl::Task previous_task; | 162 base::PendingTask previous_task((tracked_objects::Location()), |
| 163 (base::Closure())); |
158 for (int i = 0; i < work_batch_size_; i++) { | 164 for (int i = 0; i < work_batch_size_; i++) { |
159 internal::TaskQueueImpl* queue; | 165 internal::TaskQueueImpl* queue; |
160 if (!SelectQueueToService(&queue)) | 166 if (!SelectQueueToService(&queue)) |
161 return; | 167 return; |
162 // Note that this function won't post another call to DoWork if one is | 168 // Note that this function won't post another call to DoWork if one is |
163 // already pending, so it is safe to call it in a loop. | 169 // already pending, so it is safe to call it in a loop. |
164 MaybePostDoWorkOnMainRunner(); | 170 MaybePostDoWorkOnMainRunner(); |
165 | 171 |
166 if (ProcessTaskFromWorkQueue(queue, &previous_task)) | 172 if (ProcessTaskFromWorkQueue(queue, &previous_task)) |
167 return; // The TaskQueueManager got deleted, we must bail out. | 173 return; // The TaskQueueManager got deleted, we must bail out. |
(...skipping 11 matching lines...) Expand all Loading... |
179 | 185 |
180 bool TaskQueueManager::SelectQueueToService( | 186 bool TaskQueueManager::SelectQueueToService( |
181 internal::TaskQueueImpl** out_queue) { | 187 internal::TaskQueueImpl** out_queue) { |
182 bool should_run = selector_.SelectQueueToService(out_queue); | 188 bool should_run = selector_.SelectQueueToService(out_queue); |
183 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 189 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
184 disabled_by_default_tracing_category_, "TaskQueueManager", this, | 190 disabled_by_default_tracing_category_, "TaskQueueManager", this, |
185 AsValueWithSelectorResult(should_run, *out_queue)); | 191 AsValueWithSelectorResult(should_run, *out_queue)); |
186 return should_run; | 192 return should_run; |
187 } | 193 } |
188 | 194 |
189 void TaskQueueManager::DidQueueTask( | 195 void TaskQueueManager::DidQueueTask(const base::PendingTask& pending_task) { |
190 const internal::TaskQueueImpl::Task& pending_task) { | |
191 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task); | 196 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task); |
192 } | 197 } |
193 | 198 |
194 bool TaskQueueManager::ProcessTaskFromWorkQueue( | 199 bool TaskQueueManager::ProcessTaskFromWorkQueue( |
195 internal::TaskQueueImpl* queue, | 200 internal::TaskQueueImpl* queue, |
196 internal::TaskQueueImpl::Task* out_previous_task) { | 201 base::PendingTask* out_previous_task) { |
197 DCHECK(main_thread_checker_.CalledOnValidThread()); | 202 DCHECK(main_thread_checker_.CalledOnValidThread()); |
198 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); | 203 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); |
199 // TODO(alexclarke): consider std::move() when allowed. | 204 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
200 internal::TaskQueueImpl::Task pending_task = queue->TakeTaskFromWorkQueue(); | |
201 | 205 |
202 if (queue->GetQuiescenceMonitored()) | 206 if (queue->GetQuiescenceMonitored()) |
203 task_was_run_on_quiescence_monitored_queue_ = true; | 207 task_was_run_on_quiescence_monitored_queue_ = true; |
204 | 208 |
205 if (!pending_task.nestable && main_task_runner_->IsNested()) { | 209 if (!pending_task.nestable && main_task_runner_->IsNested()) { |
206 // Defer non-nestable work to the main task runner. NOTE these tasks can be | 210 // Defer non-nestable work to the main task runner. NOTE these tasks can be |
207 // arbitrarily delayed so the additional delay should not be a problem. | 211 // arbitrarily delayed so the additional delay should not be a problem. |
208 main_task_runner_->PostNonNestableTask(pending_task.posted_from, | 212 main_task_runner_->PostNonNestableTask(pending_task.posted_from, |
209 pending_task.task); | 213 pending_task.task); |
210 } else { | 214 } else { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 state->EndArray(); | 309 state->EndArray(); |
306 return state; | 310 return state; |
307 } | 311 } |
308 | 312 |
309 void TaskQueueManager::OnTaskQueueEnabled() { | 313 void TaskQueueManager::OnTaskQueueEnabled() { |
310 DCHECK(main_thread_checker_.CalledOnValidThread()); | 314 DCHECK(main_thread_checker_.CalledOnValidThread()); |
311 MaybePostDoWorkOnMainRunner(); | 315 MaybePostDoWorkOnMainRunner(); |
312 } | 316 } |
313 | 317 |
314 } // namespace scheduler | 318 } // namespace scheduler |
OLD | NEW |