| 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 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 681 base::PendingTask previous_task((tracked_objects::Location()), | 681 base::PendingTask previous_task((tracked_objects::Location()), |
| 682 (base::Closure())); | 682 (base::Closure())); |
| 683 for (int i = 0; i < work_batch_size_; i++) { | 683 for (int i = 0; i < work_batch_size_; i++) { |
| 684 size_t queue_index; | 684 size_t queue_index; |
| 685 if (!SelectWorkQueueToService(&queue_index)) | 685 if (!SelectWorkQueueToService(&queue_index)) |
| 686 return; | 686 return; |
| 687 // Note that this function won't post another call to DoWork if one is | 687 // Note that this function won't post another call to DoWork if one is |
| 688 // already pending, so it is safe to call it in a loop. | 688 // already pending, so it is safe to call it in a loop. |
| 689 MaybePostDoWorkOnMainRunner(); | 689 MaybePostDoWorkOnMainRunner(); |
| 690 | 690 |
| 691 if (ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task)) | 691 if (ProcessTaskFromWorkQueue(queue_index, &previous_task)) |
| 692 return; // The TaskQueueManager got deleted, we must bail out. | 692 return; // The TaskQueueManager got deleted, we must bail out. |
| 693 | 693 |
| 694 bool should_trigger_wakeup = Queue(queue_index)->wakeup_policy() == | 694 bool should_trigger_wakeup = Queue(queue_index)->wakeup_policy() == |
| 695 WakeupPolicy::CAN_WAKE_OTHER_QUEUES; | 695 WakeupPolicy::CAN_WAKE_OTHER_QUEUES; |
| 696 if (!UpdateWorkQueues(should_trigger_wakeup, &previous_task)) | 696 if (!UpdateWorkQueues(should_trigger_wakeup, &previous_task)) |
| 697 return; | 697 return; |
| 698 } | 698 } |
| 699 } | 699 } |
| 700 | 700 |
| 701 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { | 701 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { |
| 702 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); | 702 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); |
| 703 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 703 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 704 disabled_by_default_tracing_category_, "TaskQueueManager", this, | 704 disabled_by_default_tracing_category_, "TaskQueueManager", this, |
| 705 AsValueWithSelectorResult(should_run, *out_queue_index)); | 705 AsValueWithSelectorResult(should_run, *out_queue_index)); |
| 706 return should_run; | 706 return should_run; |
| 707 } | 707 } |
| 708 | 708 |
| 709 void TaskQueueManager::DidQueueTask(const base::PendingTask& pending_task) { | 709 void TaskQueueManager::DidQueueTask(const base::PendingTask& pending_task) { |
| 710 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task); | 710 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task); |
| 711 } | 711 } |
| 712 | 712 |
| 713 bool TaskQueueManager::ProcessTaskFromWorkQueue( | 713 bool TaskQueueManager::ProcessTaskFromWorkQueue( |
| 714 size_t queue_index, | 714 size_t queue_index, |
| 715 bool has_previous_task, | 715 base::PendingTask* out_task) { |
| 716 base::PendingTask* previous_task) { | |
| 717 DCHECK(main_thread_checker_.CalledOnValidThread()); | 716 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 718 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); | 717 scoped_refptr<DeletionSentinel> protect(deletion_sentinel_); |
| 719 internal::TaskQueueImpl* queue = Queue(queue_index); | 718 internal::TaskQueueImpl* queue = Queue(queue_index); |
| 720 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); | 719 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
| 721 task_was_run_bitmap_ |= UINT64_C(1) << queue_index; | 720 task_was_run_bitmap_ |= UINT64_C(1) << queue_index; |
| 722 if (!pending_task.nestable && main_task_runner_->IsNested()) { | 721 if (!pending_task.nestable && main_task_runner_->IsNested()) { |
| 723 // Defer non-nestable work to the main task runner. NOTE these tasks can be | 722 // Defer non-nestable work to the main task runner. NOTE these tasks can be |
| 724 // arbitrarily delayed so the additional delay should not be a problem. | 723 // arbitrarily delayed so the additional delay should not be a problem. |
| 725 main_task_runner_->PostNonNestableTask(pending_task.posted_from, | 724 main_task_runner_->PostNonNestableTask(pending_task.posted_from, |
| 726 pending_task.task); | 725 pending_task.task); |
| 727 } else { | 726 } else { |
| 728 // Suppress "will" task observer notifications for the first and "did" | |
| 729 // notifications for the last task in the batch to avoid duplicate | |
| 730 // notifications. | |
| 731 if (has_previous_task) { | |
| 732 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, | |
| 733 DidProcessTask(*previous_task)); | |
| 734 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, | |
| 735 WillProcessTask(pending_task)); | |
| 736 } | |
| 737 | |
| 738 TRACE_TASK_EXECUTION("TaskQueueManager::ProcessTaskFromWorkQueue", | 727 TRACE_TASK_EXECUTION("TaskQueueManager::ProcessTaskFromWorkQueue", |
| 739 pending_task); | 728 pending_task); |
| 729 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, |
| 730 WillProcessTask(pending_task)); |
| 740 task_annotator_.RunTask("TaskQueueManager::PostTask", pending_task); | 731 task_annotator_.RunTask("TaskQueueManager::PostTask", pending_task); |
| 741 | 732 |
| 742 // Detect if the TaskQueueManager just got deleted. If this happens we must | 733 // Detect if the TaskQueueManager just got deleted. If this happens we must |
| 743 // not access any member variables after this point. | 734 // not access any member variables after this point. |
| 744 if (protect->HasOneRef()) | 735 if (protect->HasOneRef()) |
| 745 return true; | 736 return true; |
| 746 | 737 |
| 738 FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver, task_observers_, |
| 739 DidProcessTask(pending_task)); |
| 740 |
| 747 pending_task.task.Reset(); | 741 pending_task.task.Reset(); |
| 748 *previous_task = pending_task; | 742 *out_task = pending_task; |
| 749 } | 743 } |
| 750 return false; | 744 return false; |
| 751 } | 745 } |
| 752 | 746 |
| 753 bool TaskQueueManager::RunsTasksOnCurrentThread() const { | 747 bool TaskQueueManager::RunsTasksOnCurrentThread() const { |
| 754 return main_task_runner_->RunsTasksOnCurrentThread(); | 748 return main_task_runner_->RunsTasksOnCurrentThread(); |
| 755 } | 749 } |
| 756 | 750 |
| 757 bool TaskQueueManager::PostDelayedTask( | 751 bool TaskQueueManager::PostDelayedTask( |
| 758 const tracked_objects::Location& from_here, | 752 const tracked_objects::Location& from_here, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 770 | 764 |
| 771 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { | 765 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { |
| 772 DCHECK(main_thread_checker_.CalledOnValidThread()); | 766 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 773 DCHECK_GE(work_batch_size, 1); | 767 DCHECK_GE(work_batch_size, 1); |
| 774 work_batch_size_ = work_batch_size; | 768 work_batch_size_ = work_batch_size; |
| 775 } | 769 } |
| 776 | 770 |
| 777 void TaskQueueManager::AddTaskObserver( | 771 void TaskQueueManager::AddTaskObserver( |
| 778 base::MessageLoop::TaskObserver* task_observer) { | 772 base::MessageLoop::TaskObserver* task_observer) { |
| 779 DCHECK(main_thread_checker_.CalledOnValidThread()); | 773 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 780 main_task_runner_->AddTaskObserver(task_observer); | |
| 781 task_observers_.AddObserver(task_observer); | 774 task_observers_.AddObserver(task_observer); |
| 782 } | 775 } |
| 783 | 776 |
| 784 void TaskQueueManager::RemoveTaskObserver( | 777 void TaskQueueManager::RemoveTaskObserver( |
| 785 base::MessageLoop::TaskObserver* task_observer) { | 778 base::MessageLoop::TaskObserver* task_observer) { |
| 786 DCHECK(main_thread_checker_.CalledOnValidThread()); | 779 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 787 main_task_runner_->RemoveTaskObserver(task_observer); | |
| 788 task_observers_.RemoveObserver(task_observer); | 780 task_observers_.RemoveObserver(task_observer); |
| 789 } | 781 } |
| 790 | 782 |
| 791 void TaskQueueManager::SetTimeSourceForTesting( | 783 void TaskQueueManager::SetTimeSourceForTesting( |
| 792 scoped_ptr<base::TickClock> time_source) { | 784 scoped_ptr<base::TickClock> time_source) { |
| 793 DCHECK(main_thread_checker_.CalledOnValidThread()); | 785 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 794 time_source_ = time_source.Pass(); | 786 time_source_ = time_source.Pass(); |
| 795 } | 787 } |
| 796 | 788 |
| 797 uint64 TaskQueueManager::GetAndClearTaskWasRunOnQueueBitmap() { | 789 uint64 TaskQueueManager::GetAndClearTaskWasRunOnQueueBitmap() { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 855 return nullptr; | 847 return nullptr; |
| 856 } | 848 } |
| 857 } | 849 } |
| 858 | 850 |
| 859 void TaskQueueManager::OnTaskQueueEnabled() { | 851 void TaskQueueManager::OnTaskQueueEnabled() { |
| 860 DCHECK(main_thread_checker_.CalledOnValidThread()); | 852 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 861 MaybePostDoWorkOnMainRunner(); | 853 MaybePostDoWorkOnMainRunner(); |
| 862 } | 854 } |
| 863 | 855 |
| 864 } // namespace scheduler | 856 } // namespace scheduler |
| OLD | NEW |