| 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 "content/renderer/scheduler/task_queue_manager.h" | 5 #include "content/renderer/scheduler/task_queue_manager.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 TaskQueueManager::TaskRunnerForQueue(size_t queue_index) const { | 310 TaskQueueManager::TaskRunnerForQueue(size_t queue_index) const { |
| 311 return Queue(queue_index); | 311 return Queue(queue_index); |
| 312 } | 312 } |
| 313 | 313 |
| 314 bool TaskQueueManager::IsQueueEmpty(size_t queue_index) const { | 314 bool TaskQueueManager::IsQueueEmpty(size_t queue_index) const { |
| 315 internal::TaskQueue* queue = Queue(queue_index); | 315 internal::TaskQueue* queue = Queue(queue_index); |
| 316 return queue->IsQueueEmpty(); | 316 return queue->IsQueueEmpty(); |
| 317 } | 317 } |
| 318 | 318 |
| 319 void TaskQueueManager::SetAutoPump(size_t queue_index, bool auto_pump) { | 319 void TaskQueueManager::SetAutoPump(size_t queue_index, bool auto_pump) { |
| 320 main_thread_checker_.CalledOnValidThread(); | 320 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 321 internal::TaskQueue* queue = Queue(queue_index); | 321 internal::TaskQueue* queue = Queue(queue_index); |
| 322 queue->SetAutoPump(auto_pump); | 322 queue->SetAutoPump(auto_pump); |
| 323 } | 323 } |
| 324 | 324 |
| 325 void TaskQueueManager::PumpQueue(size_t queue_index) { | 325 void TaskQueueManager::PumpQueue(size_t queue_index) { |
| 326 main_thread_checker_.CalledOnValidThread(); | 326 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 327 internal::TaskQueue* queue = Queue(queue_index); | 327 internal::TaskQueue* queue = Queue(queue_index); |
| 328 queue->PumpQueue(); | 328 queue->PumpQueue(); |
| 329 } | 329 } |
| 330 | 330 |
| 331 bool TaskQueueManager::UpdateWorkQueues( | 331 bool TaskQueueManager::UpdateWorkQueues( |
| 332 base::TimeTicks* next_pending_delayed_task) { | 332 base::TimeTicks* next_pending_delayed_task) { |
| 333 // TODO(skyostil): This is not efficient when the number of queues grows very | 333 // TODO(skyostil): This is not efficient when the number of queues grows very |
| 334 // large due to the number of locks taken. Consider optimizing when we get | 334 // large due to the number of locks taken. Consider optimizing when we get |
| 335 // there. | 335 // there. |
| 336 main_thread_checker_.CalledOnValidThread(); | 336 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 337 bool has_work = false; | 337 bool has_work = false; |
| 338 for (auto& queue : queues_) { | 338 for (auto& queue : queues_) { |
| 339 has_work |= queue->UpdateWorkQueue(next_pending_delayed_task); | 339 has_work |= queue->UpdateWorkQueue(next_pending_delayed_task); |
| 340 if (!queue->work_queue().empty()) { | 340 if (!queue->work_queue().empty()) { |
| 341 // Currently we should not be getting tasks with delayed run times in any | 341 // Currently we should not be getting tasks with delayed run times in any |
| 342 // of the work queues. | 342 // of the work queues. |
| 343 DCHECK(queue->work_queue().front().delayed_run_time.is_null()); | 343 DCHECK(queue->work_queue().front().delayed_run_time.is_null()); |
| 344 } | 344 } |
| 345 } | 345 } |
| 346 return has_work; | 346 return has_work; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 360 main_task_runner_->PostTask( | 360 main_task_runner_->PostTask( |
| 361 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_, | 361 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_, |
| 362 on_main_thread)); | 362 on_main_thread)); |
| 363 } | 363 } |
| 364 | 364 |
| 365 void TaskQueueManager::DoWork(bool posted_from_main_thread) { | 365 void TaskQueueManager::DoWork(bool posted_from_main_thread) { |
| 366 if (posted_from_main_thread) { | 366 if (posted_from_main_thread) { |
| 367 pending_dowork_count_--; | 367 pending_dowork_count_--; |
| 368 DCHECK_GE(pending_dowork_count_, 0); | 368 DCHECK_GE(pending_dowork_count_, 0); |
| 369 } | 369 } |
| 370 main_thread_checker_.CalledOnValidThread(); | 370 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 371 | 371 |
| 372 base::TimeTicks next_pending_delayed_task( | 372 base::TimeTicks next_pending_delayed_task( |
| 373 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); | 373 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); |
| 374 for (int i = 0; i < work_batch_size_; i++) { | 374 for (int i = 0; i < work_batch_size_; i++) { |
| 375 if (!UpdateWorkQueues(&next_pending_delayed_task)) | 375 if (!UpdateWorkQueues(&next_pending_delayed_task)) |
| 376 return; | 376 return; |
| 377 | 377 |
| 378 // Interrupt the work batch if we should run the next delayed task. | 378 // Interrupt the work batch if we should run the next delayed task. |
| 379 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && | 379 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && |
| 380 Now() >= next_pending_delayed_task) | 380 Now() >= next_pending_delayed_task) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 397 AsValueWithSelectorResult(should_run, *out_queue_index)); | 397 AsValueWithSelectorResult(should_run, *out_queue_index)); |
| 398 return should_run; | 398 return should_run; |
| 399 } | 399 } |
| 400 | 400 |
| 401 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { | 401 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { |
| 402 pending_task->sequence_num = task_sequence_num_.GetNext(); | 402 pending_task->sequence_num = task_sequence_num_.GetNext(); |
| 403 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); | 403 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); |
| 404 } | 404 } |
| 405 | 405 |
| 406 void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) { | 406 void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) { |
| 407 main_thread_checker_.CalledOnValidThread(); | 407 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 408 internal::TaskQueue* queue = Queue(queue_index); | 408 internal::TaskQueue* queue = Queue(queue_index); |
| 409 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); | 409 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
| 410 if (!pending_task.nestable) { | 410 if (!pending_task.nestable) { |
| 411 // Defer non-nestable work to the main task runner. NOTE these tasks can be | 411 // Defer non-nestable work to the main task runner. NOTE these tasks can be |
| 412 // arbitrarily delayed so the additional delay should not be a problem. | 412 // arbitrarily delayed so the additional delay should not be a problem. |
| 413 main_task_runner_->PostNonNestableTask(pending_task.posted_from, | 413 main_task_runner_->PostNonNestableTask(pending_task.posted_from, |
| 414 pending_task.task); | 414 pending_task.task); |
| 415 } else { | 415 } else { |
| 416 task_annotator_.RunTask("TaskQueueManager::PostTask", | 416 task_annotator_.RunTask("TaskQueueManager::PostTask", |
| 417 "TaskQueueManager::RunTask", pending_task); | 417 "TaskQueueManager::RunTask", pending_task); |
| 418 } | 418 } |
| 419 } | 419 } |
| 420 | 420 |
| 421 bool TaskQueueManager::RunsTasksOnCurrentThread() const { | 421 bool TaskQueueManager::RunsTasksOnCurrentThread() const { |
| 422 return main_task_runner_->RunsTasksOnCurrentThread(); | 422 return main_task_runner_->RunsTasksOnCurrentThread(); |
| 423 } | 423 } |
| 424 | 424 |
| 425 bool TaskQueueManager::PostDelayedTask( | 425 bool TaskQueueManager::PostDelayedTask( |
| 426 const tracked_objects::Location& from_here, | 426 const tracked_objects::Location& from_here, |
| 427 const base::Closure& task, | 427 const base::Closure& task, |
| 428 base::TimeDelta delay) { | 428 base::TimeDelta delay) { |
| 429 DCHECK(delay > base::TimeDelta()); | 429 DCHECK(delay > base::TimeDelta()); |
| 430 return main_task_runner_->PostDelayedTask(from_here, task, delay); | 430 return main_task_runner_->PostDelayedTask(from_here, task, delay); |
| 431 } | 431 } |
| 432 | 432 |
| 433 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { | 433 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { |
| 434 main_thread_checker_.CalledOnValidThread(); | 434 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 435 internal::TaskQueue* queue = Queue(queue_index); | 435 internal::TaskQueue* queue = Queue(queue_index); |
| 436 queue->set_name(name); | 436 queue->set_name(name); |
| 437 } | 437 } |
| 438 | 438 |
| 439 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { | 439 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { |
| 440 main_thread_checker_.CalledOnValidThread(); | 440 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 441 DCHECK_GE(work_batch_size, 1); | 441 DCHECK_GE(work_batch_size, 1); |
| 442 work_batch_size_ = work_batch_size; | 442 work_batch_size_ = work_batch_size; |
| 443 } | 443 } |
| 444 | 444 |
| 445 void TaskQueueManager::SetTimeSourceForTesting( | 445 void TaskQueueManager::SetTimeSourceForTesting( |
| 446 scoped_refptr<cc::TestNowSource> time_source) { | 446 scoped_refptr<cc::TestNowSource> time_source) { |
| 447 main_thread_checker_.CalledOnValidThread(); | 447 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 448 time_source_ = time_source; | 448 time_source_ = time_source; |
| 449 } | 449 } |
| 450 | 450 |
| 451 base::TimeTicks TaskQueueManager::Now() const { | 451 base::TimeTicks TaskQueueManager::Now() const { |
| 452 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); | 452 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); |
| 453 } | 453 } |
| 454 | 454 |
| 455 scoped_refptr<base::debug::ConvertableToTraceFormat> | 455 scoped_refptr<base::debug::ConvertableToTraceFormat> |
| 456 TaskQueueManager::AsValueWithSelectorResult(bool should_run, | 456 TaskQueueManager::AsValueWithSelectorResult(bool should_run, |
| 457 size_t selected_queue) const { | 457 size_t selected_queue) const { |
| 458 main_thread_checker_.CalledOnValidThread(); | 458 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 459 scoped_refptr<base::debug::TracedValue> state = | 459 scoped_refptr<base::debug::TracedValue> state = |
| 460 new base::debug::TracedValue(); | 460 new base::debug::TracedValue(); |
| 461 state->BeginArray("queues"); | 461 state->BeginArray("queues"); |
| 462 for (auto& queue : queues_) | 462 for (auto& queue : queues_) |
| 463 queue->AsValueInto(state.get()); | 463 queue->AsValueInto(state.get()); |
| 464 state->EndArray(); | 464 state->EndArray(); |
| 465 state->BeginDictionary("selector"); | 465 state->BeginDictionary("selector"); |
| 466 selector_->AsValueInto(state.get()); | 466 selector_->AsValueInto(state.get()); |
| 467 state->EndDictionary(); | 467 state->EndDictionary(); |
| 468 if (should_run) | 468 if (should_run) |
| 469 state->SetInteger("selected_queue", selected_queue); | 469 state->SetInteger("selected_queue", selected_queue); |
| 470 return state; | 470 return state; |
| 471 } | 471 } |
| 472 | 472 |
| 473 } // namespace content | 473 } // namespace content |
| OLD | NEW |