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 "platform/scheduler/base/task_queue_manager.h" | 5 #include "platform/scheduler/base/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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 if (observer_) | 121 if (observer_) |
122 observer_->OnUnregisterTaskQueue(task_queue); | 122 observer_->OnUnregisterTaskQueue(task_queue); |
123 | 123 |
124 // Add |task_queue| to |queues_to_delete_| so we can prevent it from being | 124 // Add |task_queue| to |queues_to_delete_| so we can prevent it from being |
125 // freed while any of our structures hold hold a raw pointer to it. | 125 // freed while any of our structures hold hold a raw pointer to it. |
126 queues_to_delete_.insert(task_queue); | 126 queues_to_delete_.insert(task_queue); |
127 queues_.erase(task_queue); | 127 queues_.erase(task_queue); |
128 selector_.RemoveQueue(task_queue.get()); | 128 selector_.RemoveQueue(task_queue.get()); |
129 } | 129 } |
130 | 130 |
131 void TaskQueueManager::UpdateWorkQueues( | 131 void TaskQueueManager::UpdateWorkQueues(LazyNow lazy_now) { |
132 bool should_trigger_wakeup, | |
133 const internal::TaskQueueImpl::Task* previous_task, | |
134 LazyNow lazy_now) { | |
135 TRACE_EVENT0(disabled_by_default_tracing_category_, | 132 TRACE_EVENT0(disabled_by_default_tracing_category_, |
136 "TaskQueueManager::UpdateWorkQueues"); | 133 "TaskQueueManager::UpdateWorkQueues"); |
137 | 134 |
138 for (TimeDomain* time_domain : time_domains_) { | 135 for (TimeDomain* time_domain : time_domains_) { |
139 LazyNow lazy_now_in_domain = time_domain == real_time_domain_.get() | 136 LazyNow lazy_now_in_domain = time_domain == real_time_domain_.get() |
140 ? lazy_now | 137 ? lazy_now |
141 : time_domain->CreateLazyNow(); | 138 : time_domain->CreateLazyNow(); |
142 time_domain->UpdateWorkQueues(should_trigger_wakeup, previous_task, | 139 time_domain->UpdateWorkQueues(lazy_now_in_domain); |
143 lazy_now_in_domain); | |
144 } | 140 } |
145 } | 141 } |
146 | 142 |
147 void TaskQueueManager::MaybeScheduleImmediateWork( | 143 void TaskQueueManager::MaybeScheduleImmediateWork( |
148 const tracked_objects::Location& from_here) { | 144 const tracked_objects::Location& from_here) { |
149 bool on_main_thread = delegate_->BelongsToCurrentThread(); | 145 bool on_main_thread = delegate_->BelongsToCurrentThread(); |
150 // De-duplicate DoWork posts. | 146 // De-duplicate DoWork posts. |
151 if (on_main_thread) { | 147 if (on_main_thread) { |
152 if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second) { | 148 if (!main_thread_pending_wakeups_.insert(base::TimeTicks()).second) { |
153 return; | 149 return; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 | 189 |
194 if (!delegate_->IsNested()) | 190 if (!delegate_->IsNested()) |
195 queues_to_delete_.clear(); | 191 queues_to_delete_.clear(); |
196 | 192 |
197 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); | 193 LazyNow lazy_now(real_time_domain()->CreateLazyNow()); |
198 base::TimeTicks task_start_time; | 194 base::TimeTicks task_start_time; |
199 | 195 |
200 if (!delegate_->IsNested() && task_time_tracker_) | 196 if (!delegate_->IsNested() && task_time_tracker_) |
201 task_start_time = lazy_now.Now(); | 197 task_start_time = lazy_now.Now(); |
202 | 198 |
203 // Pass false and nullptr to UpdateWorkQueues here to prevent waking up a | 199 // TODO(alexclarke): Get rid of this and call oncer per loop iteration. |
Sami
2016/08/25 15:54:12
typo: once
alex clarke (OOO till 29th)
2016/08/26 13:29:08
Done.
| |
204 // pump-after-wakeup queue. | 200 UpdateWorkQueues(lazy_now); |
205 UpdateWorkQueues(false, nullptr, lazy_now); | |
206 | |
207 internal::TaskQueueImpl::Task previous_task; | |
208 | 201 |
209 for (int i = 0; i < work_batch_size_; i++) { | 202 for (int i = 0; i < work_batch_size_; i++) { |
210 internal::WorkQueue* work_queue; | 203 internal::WorkQueue* work_queue; |
211 if (!SelectWorkQueueToService(&work_queue)) { | 204 if (!SelectWorkQueueToService(&work_queue)) |
212 break; | 205 break; |
213 } | |
214 | 206 |
215 bool should_trigger_wakeup = work_queue->task_queue()->wakeup_policy() == | 207 switch (ProcessTaskFromWorkQueue(work_queue)) { |
216 TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES; | |
217 | |
218 switch (ProcessTaskFromWorkQueue(work_queue, &previous_task)) { | |
219 case ProcessTaskResult::DEFERRED: | 208 case ProcessTaskResult::DEFERRED: |
220 // If a task was deferred, try again with another task. Note that this | 209 // If a task was deferred, try again with another task. |
221 // means deferred tasks (i.e. non-nestable tasks) will never trigger | |
222 // queue wake-ups. | |
223 continue; | 210 continue; |
224 case ProcessTaskResult::EXECUTED: | 211 case ProcessTaskResult::EXECUTED: |
225 break; | 212 break; |
226 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: | 213 case ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED: |
227 return; // The TaskQueueManager got deleted, we must bail out. | 214 return; // The TaskQueueManager got deleted, we must bail out. |
228 } | 215 } |
229 | 216 |
230 lazy_now = real_time_domain()->CreateLazyNow(); | 217 lazy_now = real_time_domain()->CreateLazyNow(); |
231 if (!delegate_->IsNested() && task_time_tracker_) { | 218 if (!delegate_->IsNested() && task_time_tracker_) { |
232 // Only report top level task durations. | 219 // Only report top level task durations. |
233 base::TimeTicks task_end_time = lazy_now.Now(); | 220 base::TimeTicks task_end_time = lazy_now.Now(); |
234 task_time_tracker_->ReportTaskTime(task_start_time, task_end_time); | 221 task_time_tracker_->ReportTaskTime(task_start_time, task_end_time); |
235 task_start_time = task_end_time; | 222 task_start_time = task_end_time; |
236 } | 223 } |
237 | 224 |
238 work_queue = nullptr; // The queue may have been unregistered. | 225 work_queue = nullptr; // The queue may have been unregistered. |
239 | 226 |
240 UpdateWorkQueues(should_trigger_wakeup, &previous_task, lazy_now); | 227 UpdateWorkQueues(lazy_now); |
241 | 228 |
242 // Only run a single task per batch in nested run loops so that we can | 229 // Only run a single task per batch in nested run loops so that we can |
243 // properly exit the nested loop when someone calls RunLoop::Quit(). | 230 // properly exit the nested loop when someone calls RunLoop::Quit(). |
244 if (delegate_->IsNested()) | 231 if (delegate_->IsNested()) |
245 break; | 232 break; |
246 } | 233 } |
247 | 234 |
248 // TODO(alexclarke): Consider refactoring the above loop to terminate only | 235 // TODO(alexclarke): Consider refactoring the above loop to terminate only |
249 // when there's no more work left to be done, rather than posting a | 236 // when there's no more work left to be done, rather than posting a |
250 // continuation task. | 237 // continuation task. |
(...skipping 17 matching lines...) Expand all Loading... | |
268 AsValueWithSelectorResult(should_run, *out_work_queue)); | 255 AsValueWithSelectorResult(should_run, *out_work_queue)); |
269 return should_run; | 256 return should_run; |
270 } | 257 } |
271 | 258 |
272 void TaskQueueManager::DidQueueTask( | 259 void TaskQueueManager::DidQueueTask( |
273 const internal::TaskQueueImpl::Task& pending_task) { | 260 const internal::TaskQueueImpl::Task& pending_task) { |
274 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task); | 261 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task); |
275 } | 262 } |
276 | 263 |
277 TaskQueueManager::ProcessTaskResult TaskQueueManager::ProcessTaskFromWorkQueue( | 264 TaskQueueManager::ProcessTaskResult TaskQueueManager::ProcessTaskFromWorkQueue( |
278 internal::WorkQueue* work_queue, | 265 internal::WorkQueue* work_queue) { |
279 internal::TaskQueueImpl::Task* out_previous_task) { | |
280 DCHECK(main_thread_checker_.CalledOnValidThread()); | 266 DCHECK(main_thread_checker_.CalledOnValidThread()); |
281 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); | 267 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); |
282 internal::TaskQueueImpl* queue = work_queue->task_queue(); | 268 internal::TaskQueueImpl* queue = work_queue->task_queue(); |
283 | 269 |
284 if (queue->GetQuiescenceMonitored()) | 270 if (queue->GetQuiescenceMonitored()) |
285 task_was_run_on_quiescence_monitored_queue_ = true; | 271 task_was_run_on_quiescence_monitored_queue_ = true; |
286 | 272 |
287 internal::TaskQueueImpl::Task pending_task = | 273 internal::TaskQueueImpl::Task pending_task = |
288 work_queue->TakeTaskFromWorkQueue(); | 274 work_queue->TakeTaskFromWorkQueue(); |
289 if (!pending_task.nestable && delegate_->IsNested()) { | 275 if (!pending_task.nestable && delegate_->IsNested()) { |
(...skipping 30 matching lines...) Expand all Loading... | |
320 return ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED; | 306 return ProcessTaskResult::TASK_QUEUE_MANAGER_DELETED; |
321 | 307 |
322 currently_executing_task_queue_ = prev_executing_task_queue; | 308 currently_executing_task_queue_ = prev_executing_task_queue; |
323 | 309 |
324 if (queue->GetShouldNotifyObservers()) { | 310 if (queue->GetShouldNotifyObservers()) { |
325 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, | 311 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, |
326 DidProcessTask(pending_task)); | 312 DidProcessTask(pending_task)); |
327 queue->NotifyDidProcessTask(pending_task); | 313 queue->NotifyDidProcessTask(pending_task); |
328 } | 314 } |
329 | 315 |
330 pending_task.task.Reset(); | |
331 *out_previous_task = std::move(pending_task); | |
332 return ProcessTaskResult::EXECUTED; | 316 return ProcessTaskResult::EXECUTED; |
333 } | 317 } |
334 | 318 |
335 void TaskQueueManager::MaybeRecordTaskDelayHistograms( | 319 void TaskQueueManager::MaybeRecordTaskDelayHistograms( |
336 const internal::TaskQueueImpl::Task& pending_task, | 320 const internal::TaskQueueImpl::Task& pending_task, |
337 const internal::TaskQueueImpl* queue) { | 321 const internal::TaskQueueImpl* queue) { |
338 if ((task_count_++ % kRecordRecordTaskDelayHistogramsEveryNTasks) != 0) | 322 if ((task_count_++ % kRecordRecordTaskDelayHistogramsEveryNTasks) != 0) |
339 return; | 323 return; |
340 | 324 |
341 // Record delayed task lateness and immediate task queueing durations, but | 325 // Record delayed task lateness and immediate task queueing durations, but |
Sami
2016/08/25 15:54:12
Looks like this comment needs updating.
alex clarke (OOO till 29th)
2016/08/26 13:29:08
Done.
| |
342 // only for auto-pumped queues. Manually pumped and after wakeup queues can | 326 // only for auto-pumped queues. Manually pumped and after wakeup queues can |
343 // have arbitarially large delayes, which would cloud any analysis. | 327 // have arbitarially large delayes, which would cloud any analysis. |
344 if (queue->GetPumpPolicy() == TaskQueue::PumpPolicy::AUTO) { | 328 if (!pending_task.delayed_run_time.is_null()) { |
345 if (!pending_task.delayed_run_time.is_null()) { | 329 RecordDelayedTaskLateness(delegate_->NowTicks() - |
346 RecordDelayedTaskLateness(delegate_->NowTicks() - | 330 pending_task.delayed_run_time); |
347 pending_task.delayed_run_time); | 331 } else if (!pending_task.time_posted.is_null()) { |
348 } else if (!pending_task.time_posted.is_null()) { | 332 RecordImmediateTaskQueueingDuration(tracked_objects::TrackedTime::Now() - |
349 RecordImmediateTaskQueueingDuration(tracked_objects::TrackedTime::Now() - | 333 pending_task.time_posted); |
350 pending_task.time_posted); | |
351 } | |
352 } | 334 } |
353 } | 335 } |
354 | 336 |
355 bool TaskQueueManager::RunsTasksOnCurrentThread() const { | 337 bool TaskQueueManager::RunsTasksOnCurrentThread() const { |
356 return delegate_->RunsTasksOnCurrentThread(); | 338 return delegate_->RunsTasksOnCurrentThread(); |
357 } | 339 } |
358 | 340 |
359 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { | 341 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { |
360 DCHECK(main_thread_checker_.CalledOnValidThread()); | 342 DCHECK(main_thread_checker_.CalledOnValidThread()); |
361 DCHECK_GE(work_batch_size, 1); | 343 DCHECK_GE(work_batch_size, 1); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 DCHECK(main_thread_checker_.CalledOnValidThread()); | 416 DCHECK(main_thread_checker_.CalledOnValidThread()); |
435 DCHECK(!work_queue->Empty()); | 417 DCHECK(!work_queue->Empty()); |
436 if (observer_) { | 418 if (observer_) { |
437 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), | 419 observer_->OnTriedToExecuteBlockedTask(*work_queue->task_queue(), |
438 *work_queue->GetFrontTask()); | 420 *work_queue->GetFrontTask()); |
439 } | 421 } |
440 } | 422 } |
441 | 423 |
442 } // namespace scheduler | 424 } // namespace scheduler |
443 } // namespace blink | 425 } // namespace blink |
OLD | NEW |