Roll src/third_party/WebKit 605a979:06cb9e9 (svn 202556:202558)
[chromium-blink-merge.git] / components / scheduler / child / task_queue_selector.cc
blobd65cbf9ff2cf60267caac853ee383188805c6322
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
3 // found in the LICENSE file.
5 #include "components/scheduler/child/task_queue_selector.h"
7 #include "base/logging.h"
8 #include "base/trace_event/trace_event_argument.h"
9 #include "components/scheduler/child/task_queue_impl.h"
11 namespace scheduler {
12 namespace internal {
14 TaskQueueSelector::TaskQueueSelector()
15 : task_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT),
16 starvation_count_(0),
17 task_queue_selector_observer_(nullptr) {}
19 TaskQueueSelector::~TaskQueueSelector() {}
21 void TaskQueueSelector::AddQueue(internal::TaskQueueImpl* queue) {
22 DCHECK(main_thread_checker_.CalledOnValidThread());
23 task_queue_sets_.AssignQueueToSet(queue, TaskQueue::NORMAL_PRIORITY);
26 void TaskQueueSelector::RemoveQueue(internal::TaskQueueImpl* queue) {
27 DCHECK(main_thread_checker_.CalledOnValidThread());
28 task_queue_sets_.RemoveQueue(queue);
31 void TaskQueueSelector::SetQueuePriority(internal::TaskQueueImpl* queue,
32 TaskQueue::QueuePriority priority) {
33 DCHECK(main_thread_checker_.CalledOnValidThread());
34 DCHECK_LT(priority, TaskQueue::QUEUE_PRIORITY_COUNT);
35 TaskQueue::QueuePriority old_priority =
36 static_cast<TaskQueue::QueuePriority>(queue->get_task_queue_set_index());
37 task_queue_sets_.AssignQueueToSet(queue, priority);
38 if (task_queue_selector_observer_ &&
39 old_priority == TaskQueue::DISABLED_PRIORITY) {
40 task_queue_selector_observer_->OnTaskQueueEnabled(queue);
44 bool TaskQueueSelector::IsQueueEnabled(
45 const internal::TaskQueueImpl* queue) const {
46 DCHECK(main_thread_checker_.CalledOnValidThread());
47 return static_cast<TaskQueue::QueuePriority>(
48 queue->get_task_queue_set_index()) != TaskQueue::DISABLED_PRIORITY;
51 TaskQueue::QueuePriority TaskQueueSelector::NextPriority(
52 TaskQueue::QueuePriority priority) {
53 DCHECK(priority < TaskQueue::QUEUE_PRIORITY_COUNT);
54 return static_cast<TaskQueue::QueuePriority>(static_cast<int>(priority) + 1);
57 bool TaskQueueSelector::ChooseOldestWithPriority(
58 TaskQueue::QueuePriority priority,
59 internal::TaskQueueImpl** out_queue) const {
60 return task_queue_sets_.GetOldestQueueInSet(priority, out_queue);
63 bool TaskQueueSelector::SelectQueueToService(
64 internal::TaskQueueImpl** out_queue) {
65 DCHECK(main_thread_checker_.CalledOnValidThread());
66 // Always service the control queue if it has any work.
67 if (ChooseOldestWithPriority(TaskQueue::CONTROL_PRIORITY, out_queue)) {
68 DidSelectQueueWithPriority(TaskQueue::CONTROL_PRIORITY);
69 return true;
71 // Select from the normal priority queue if we are starving it.
72 if (starvation_count_ >= kMaxStarvationTasks &&
73 ChooseOldestWithPriority(TaskQueue::NORMAL_PRIORITY, out_queue)) {
74 DidSelectQueueWithPriority(TaskQueue::NORMAL_PRIORITY);
75 return true;
77 // Otherwise choose in priority order.
78 for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY;
79 priority < TaskQueue::DISABLED_PRIORITY;
80 priority = NextPriority(priority)) {
81 if (ChooseOldestWithPriority(priority, out_queue)) {
82 DidSelectQueueWithPriority(priority);
83 return true;
86 return false;
89 void TaskQueueSelector::DidSelectQueueWithPriority(
90 TaskQueue::QueuePriority priority) {
91 switch (priority) {
92 case TaskQueue::CONTROL_PRIORITY:
93 break;
94 case TaskQueue::HIGH_PRIORITY:
95 starvation_count_++;
96 break;
97 case TaskQueue::NORMAL_PRIORITY:
98 case TaskQueue::BEST_EFFORT_PRIORITY:
99 starvation_count_ = 0;
100 break;
101 default:
102 NOTREACHED();
106 void TaskQueueSelector::AsValueInto(
107 base::trace_event::TracedValue* state) const {
108 DCHECK(main_thread_checker_.CalledOnValidThread());
109 state->SetInteger("starvation_count", starvation_count_);
112 void TaskQueueSelector::SetTaskQueueSelectorObserver(Observer* observer) {
113 task_queue_selector_observer_ = observer;
116 bool TaskQueueSelector::EnabledWorkQueuesEmpty() const {
117 for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY;
118 priority < TaskQueue::DISABLED_PRIORITY;
119 priority = NextPriority(priority)) {
120 if (!task_queue_sets_.IsSetEmpty(priority))
121 return false;
123 return true;
126 } // namespace internal
127 } // namespace scheduler