| 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/child/scheduler/task_queue_manager.h" | 5 #include "content/child/scheduler/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 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, | 457 scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, |
| 458 TaskQueueSelector* selector, | 458 TaskQueueSelector* selector, |
| 459 const char* disabled_by_default_tracing_category) | 459 const char* disabled_by_default_tracing_category) |
| 460 : main_task_runner_(main_task_runner), | 460 : main_task_runner_(main_task_runner), |
| 461 selector_(selector), | 461 selector_(selector), |
| 462 pending_dowork_count_(0), | 462 pending_dowork_count_(0), |
| 463 work_batch_size_(1), | 463 work_batch_size_(1), |
| 464 time_source_(nullptr), | 464 time_source_(nullptr), |
| 465 disabled_by_default_tracing_category_( | 465 disabled_by_default_tracing_category_( |
| 466 disabled_by_default_tracing_category), | 466 disabled_by_default_tracing_category), |
| 467 deletion_sentinel_(new DeletionSentinel()), |
| 467 weak_factory_(this) { | 468 weak_factory_(this) { |
| 468 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); | 469 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); |
| 469 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, | 470 TRACE_EVENT_OBJECT_CREATED_WITH_ID(disabled_by_default_tracing_category, |
| 470 "TaskQueueManager", this); | 471 "TaskQueueManager", this); |
| 471 | 472 |
| 472 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); | 473 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); |
| 473 for (size_t i = 0; i < task_queue_count; i++) { | 474 for (size_t i = 0; i < task_queue_count; i++) { |
| 474 scoped_refptr<internal::TaskQueue> queue(make_scoped_refptr( | 475 scoped_refptr<internal::TaskQueue> queue(make_scoped_refptr( |
| 475 new internal::TaskQueue(this, disabled_by_default_tracing_category))); | 476 new internal::TaskQueue(this, disabled_by_default_tracing_category))); |
| 476 queues_.push_back(queue); | 477 queues_.push_back(queue); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 | 590 |
| 590 base::PendingTask previous_task((tracked_objects::Location()), | 591 base::PendingTask previous_task((tracked_objects::Location()), |
| 591 (base::Closure())); | 592 (base::Closure())); |
| 592 for (int i = 0; i < work_batch_size_; i++) { | 593 for (int i = 0; i < work_batch_size_; i++) { |
| 593 size_t queue_index; | 594 size_t queue_index; |
| 594 if (!SelectWorkQueueToService(&queue_index)) | 595 if (!SelectWorkQueueToService(&queue_index)) |
| 595 return; | 596 return; |
| 596 // Note that this function won't post another call to DoWork if one is | 597 // Note that this function won't post another call to DoWork if one is |
| 597 // already pending, so it is safe to call it in a loop. | 598 // already pending, so it is safe to call it in a loop. |
| 598 MaybePostDoWorkOnMainRunner(); | 599 MaybePostDoWorkOnMainRunner(); |
| 599 ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task); | 600 |
| 601 if (ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task)) |
| 602 return; // The TaskQueueManager got deleted, we must bail out. |
| 600 | 603 |
| 601 if (!UpdateWorkQueues(&previous_task)) | 604 if (!UpdateWorkQueues(&previous_task)) |
| 602 return; | 605 return; |
| 603 } | 606 } |
| 604 } | 607 } |
| 605 | 608 |
| 606 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { | 609 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { |
| 607 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); | 610 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); |
| 608 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 611 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 609 disabled_by_default_tracing_category_, "TaskQueueManager", this, | 612 disabled_by_default_tracing_category_, "TaskQueueManager", this, |
| 610 AsValueWithSelectorResult(should_run, *out_queue_index)); | 613 AsValueWithSelectorResult(should_run, *out_queue_index)); |
| 611 return should_run; | 614 return should_run; |
| 612 } | 615 } |
| 613 | 616 |
| 614 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { | 617 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { |
| 615 pending_task->sequence_num = task_sequence_num_.GetNext(); | 618 pending_task->sequence_num = task_sequence_num_.GetNext(); |
| 616 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); | 619 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); |
| 617 } | 620 } |
| 618 | 621 |
| 619 void TaskQueueManager::ProcessTaskFromWorkQueue( | 622 bool TaskQueueManager::ProcessTaskFromWorkQueue( |
| 620 size_t queue_index, | 623 size_t queue_index, |
| 621 bool has_previous_task, | 624 bool has_previous_task, |
| 622 base::PendingTask* previous_task) { | 625 base::PendingTask* previous_task) { |
| 623 DCHECK(main_thread_checker_.CalledOnValidThread()); | 626 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 627 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); |
| 624 internal::TaskQueue* queue = Queue(queue_index); | 628 internal::TaskQueue* queue = Queue(queue_index); |
| 625 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); | 629 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
| 626 if (!pending_task.nestable && main_task_runner_->IsNested()) { | 630 if (!pending_task.nestable && main_task_runner_->IsNested()) { |
| 627 // Defer non-nestable work to the main task runner. NOTE these tasks can be | 631 // Defer non-nestable work to the main task runner. NOTE these tasks can be |
| 628 // arbitrarily delayed so the additional delay should not be a problem. | 632 // arbitrarily delayed so the additional delay should not be a problem. |
| 629 main_task_runner_->PostNonNestableTask(pending_task.posted_from, | 633 main_task_runner_->PostNonNestableTask(pending_task.posted_from, |
| 630 pending_task.task); | 634 pending_task.task); |
| 631 } else { | 635 } else { |
| 632 // Suppress "will" task observer notifications for the first and "did" | 636 // Suppress "will" task observer notifications for the first and "did" |
| 633 // notifications for the last task in the batch to avoid duplicate | 637 // notifications for the last task in the batch to avoid duplicate |
| 634 // notifications. | 638 // notifications. |
| 635 if (has_previous_task) { | 639 if (has_previous_task) { |
| 636 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, | 640 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, |
| 637 DidProcessTask(*previous_task)); | 641 DidProcessTask(*previous_task)); |
| 638 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, | 642 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, |
| 639 WillProcessTask(pending_task)); | 643 WillProcessTask(pending_task)); |
| 640 } | 644 } |
| 641 task_annotator_.RunTask("TaskQueueManager::PostTask", | 645 task_annotator_.RunTask("TaskQueueManager::PostTask", |
| 642 "TaskQueueManager::RunTask", pending_task); | 646 "TaskQueueManager::RunTask", pending_task); |
| 647 |
| 648 // Detect if the TaskQueueManager just got deleted. If this happens we must |
| 649 // not access any member variables after this point. |
| 650 if (protect->HasOneRef()) |
| 651 return true; |
| 652 |
| 643 pending_task.task.Reset(); | 653 pending_task.task.Reset(); |
| 644 *previous_task = pending_task; | 654 *previous_task = pending_task; |
| 645 } | 655 } |
| 656 return false; |
| 646 } | 657 } |
| 647 | 658 |
| 648 bool TaskQueueManager::RunsTasksOnCurrentThread() const { | 659 bool TaskQueueManager::RunsTasksOnCurrentThread() const { |
| 649 return main_task_runner_->RunsTasksOnCurrentThread(); | 660 return main_task_runner_->RunsTasksOnCurrentThread(); |
| 650 } | 661 } |
| 651 | 662 |
| 652 bool TaskQueueManager::PostDelayedTask( | 663 bool TaskQueueManager::PostDelayedTask( |
| 653 const tracked_objects::Location& from_here, | 664 const tracked_objects::Location& from_here, |
| 654 const base::Closure& task, | 665 const base::Closure& task, |
| 655 base::TimeDelta delay) { | 666 base::TimeDelta delay) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 state->EndArray(); | 716 state->EndArray(); |
| 706 state->BeginDictionary("selector"); | 717 state->BeginDictionary("selector"); |
| 707 selector_->AsValueInto(state.get()); | 718 selector_->AsValueInto(state.get()); |
| 708 state->EndDictionary(); | 719 state->EndDictionary(); |
| 709 if (should_run) | 720 if (should_run) |
| 710 state->SetInteger("selected_queue", selected_queue); | 721 state->SetInteger("selected_queue", selected_queue); |
| 711 return state; | 722 return state; |
| 712 } | 723 } |
| 713 | 724 |
| 714 } // namespace content | 725 } // namespace content |
| OLD | NEW |