OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "components/scheduler/child/task_queue_selector.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/trace_event/trace_event_argument.h" | |
9 #include "components/scheduler/child/task_queue_impl.h" | |
10 | |
11 namespace scheduler { | |
12 namespace internal { | |
13 | |
14 TaskQueueSelector::TaskQueueSelector() | |
15 : task_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT), | |
16 starvation_count_(0), | |
17 task_queue_selector_observer_(nullptr) {} | |
18 | |
19 TaskQueueSelector::~TaskQueueSelector() {} | |
20 | |
21 void TaskQueueSelector::AddQueue(internal::TaskQueueImpl* queue) { | |
22 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
23 task_queue_sets_.AssignQueueToSet(queue, TaskQueue::NORMAL_PRIORITY); | |
24 } | |
25 | |
26 void TaskQueueSelector::RemoveQueue(internal::TaskQueueImpl* queue) { | |
27 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
28 task_queue_sets_.RemoveQueue(queue); | |
29 } | |
30 | |
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); | |
41 } | |
42 } | |
43 | |
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; | |
49 } | |
50 | |
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); | |
55 } | |
56 | |
57 bool TaskQueueSelector::ChooseOldestWithPriority( | |
58 TaskQueue::QueuePriority priority, | |
59 internal::TaskQueueImpl** out_queue) const { | |
60 return task_queue_sets_.GetOldestQueueInSet(priority, out_queue); | |
61 } | |
62 | |
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; | |
70 } | |
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; | |
76 } | |
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; | |
84 } | |
85 } | |
86 return false; | |
87 } | |
88 | |
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(); | |
103 } | |
104 } | |
105 | |
106 void TaskQueueSelector::AsValueInto( | |
107 base::trace_event::TracedValue* state) const { | |
108 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
109 state->SetInteger("starvation_count", starvation_count_); | |
110 } | |
111 | |
112 void TaskQueueSelector::SetTaskQueueSelectorObserver(Observer* observer) { | |
113 task_queue_selector_observer_ = observer; | |
114 } | |
115 | |
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; | |
122 } | |
123 return true; | |
124 } | |
125 | |
126 } // namespace internal | |
127 } // namespace scheduler | |
OLD | NEW |