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 "cc/raster/task_graph_work_queue.h" | 5 #include "cc/raster/task_graph_work_queue.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
11 | 11 |
12 namespace cc { | 12 namespace cc { |
13 namespace { | |
14 | |
15 template <typename T> | |
16 void ClearAllVectors(T* array_of_vectors) { | |
reveman
2015/12/04 02:30:53
nit: remove vector specific references as T can be
ericrk
2015/12/04 19:14:31
no longer needed when using map - but good point.
| |
17 for (auto& vector : *array_of_vectors) { | |
18 vector.clear(); | |
19 } | |
20 } | |
21 | |
22 // Helper which checks if all sub arrays of a group are empty. | |
23 template <typename T> | |
24 bool AllVectorsEmpty(const T& array_of_vectors) { | |
reveman
2015/12/04 02:30:54
ditto.
maybe std::for_each and std::find_if with
ericrk
2015/12/04 19:14:31
Acknowledged.
| |
25 for (const auto& vector : array_of_vectors) { | |
26 if (!vector.empty()) | |
27 return false; | |
28 } | |
29 return true; | |
30 } | |
31 | |
32 bool CompareTaskPriority(const TaskGraphWorkQueue::PrioritizedTask& a, | |
33 const TaskGraphWorkQueue::PrioritizedTask& b) { | |
34 // In this system, numerically lower priority is run first. | |
35 return a.priority > b.priority; | |
36 } | |
37 | |
38 class CompareTaskNamespacePriority { | |
reveman
2015/12/04 02:30:54
nit: this code predates c++11 support in chromium.
ericrk
2015/12/04 19:14:30
Using a lambda directly is a lot more verbose at t
reveman
2015/12/04 20:55:50
I think this would be OK with auto for arguments b
| |
39 public: | |
40 explicit CompareTaskNamespacePriority(uint16_t group) : group_(group) {} | |
41 | |
42 bool operator()(const TaskGraphWorkQueue::TaskNamespace* a, | |
43 const TaskGraphWorkQueue::TaskNamespace* b) { | |
44 DCHECK(group_ < TaskGraphWorkQueue::kMaxTaskGroups); | |
45 DCHECK(!a->ready_to_run_tasks[group_].empty()); | |
46 DCHECK(!b->ready_to_run_tasks[group_].empty()); | |
47 | |
48 // Compare based on task priority of the ready_to_run_tasks heap .front() | |
49 // will hold the max element of the heap, except after pop_heap, when max | |
50 // element is moved to .back(). | |
51 return CompareTaskPriority(a->ready_to_run_tasks[group_].front(), | |
52 b->ready_to_run_tasks[group_].front()); | |
53 } | |
54 | |
55 private: | |
56 uint16_t group_; | |
57 }; | |
58 } // namespace | |
13 | 59 |
14 TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {} | 60 TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {} |
15 | 61 |
16 TaskGraphWorkQueue::TaskNamespace::~TaskNamespace() {} | 62 TaskGraphWorkQueue::TaskNamespace::~TaskNamespace() {} |
17 | 63 |
18 TaskGraphWorkQueue::TaskGraphWorkQueue() : next_namespace_id_(1) {} | 64 TaskGraphWorkQueue::TaskGraphWorkQueue() : next_namespace_id_(1) {} |
19 TaskGraphWorkQueue::~TaskGraphWorkQueue() {} | 65 TaskGraphWorkQueue::~TaskGraphWorkQueue() {} |
20 | 66 |
21 NamespaceToken TaskGraphWorkQueue::GetNamespaceToken() { | 67 NamespaceToken TaskGraphWorkQueue::GetNamespaceToken() { |
22 NamespaceToken token(next_namespace_id_++); | 68 NamespaceToken token(next_namespace_id_++); |
23 DCHECK(namespaces_.find(token) == namespaces_.end()); | 69 DCHECK(namespaces_.find(token) == namespaces_.end()); |
24 return token; | 70 return token; |
25 } | 71 } |
26 | 72 |
27 void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) { | 73 void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) { |
74 DCHECK(ValidateGroups(graph)); | |
75 | |
28 TaskNamespace& task_namespace = namespaces_[token]; | 76 TaskNamespace& task_namespace = namespaces_[token]; |
29 | 77 |
30 // First adjust number of dependencies to reflect completed tasks. | 78 // First adjust number of dependencies to reflect completed tasks. |
31 for (const scoped_refptr<Task>& task : task_namespace.completed_tasks) { | 79 for (const scoped_refptr<Task>& task : task_namespace.completed_tasks) { |
32 for (DependentIterator node_it(graph, task.get()); node_it; ++node_it) { | 80 for (DependentIterator node_it(graph, task.get()); node_it; ++node_it) { |
33 TaskGraph::Node& node = *node_it; | 81 TaskGraph::Node& node = *node_it; |
34 DCHECK_LT(0u, node.dependencies); | 82 DCHECK_LT(0u, node.dependencies); |
35 node.dependencies--; | 83 node.dependencies--; |
36 } | 84 } |
37 } | 85 } |
38 | 86 |
39 // Build new "ready to run" queue and remove nodes from old graph. | 87 // Build new "ready to run" queue and remove nodes from old graph. |
40 task_namespace.ready_to_run_tasks.clear(); | 88 ClearAllVectors(&task_namespace.ready_to_run_tasks); |
41 for (const TaskGraph::Node& node : graph->nodes) { | 89 for (const TaskGraph::Node& node : graph->nodes) { |
42 // Remove any old nodes that are associated with this task. The result is | 90 // Remove any old nodes that are associated with this task. The result is |
43 // that the old graph is left with all nodes not present in this graph, | 91 // that the old graph is left with all nodes not present in this graph, |
44 // which we use below to determine what tasks need to be canceled. | 92 // which we use below to determine what tasks need to be canceled. |
45 TaskGraph::Node::Vector::iterator old_it = std::find_if( | 93 TaskGraph::Node::Vector::iterator old_it = std::find_if( |
46 task_namespace.graph.nodes.begin(), task_namespace.graph.nodes.end(), | 94 task_namespace.graph.nodes.begin(), task_namespace.graph.nodes.end(), |
47 [node](const TaskGraph::Node& other) { | 95 [node](const TaskGraph::Node& other) { |
48 return node.task == other.task; | 96 return node.task == other.task; |
49 }); | 97 }); |
50 if (old_it != task_namespace.graph.nodes.end()) { | 98 if (old_it != task_namespace.graph.nodes.end()) { |
51 std::swap(*old_it, task_namespace.graph.nodes.back()); | 99 std::swap(*old_it, task_namespace.graph.nodes.back()); |
52 task_namespace.graph.nodes.pop_back(); | 100 task_namespace.graph.nodes.pop_back(); |
53 } | 101 } |
54 | 102 |
55 // Task is not ready to run if dependencies are not yet satisfied. | 103 // Task is not ready to run if dependencies are not yet satisfied. |
56 if (node.dependencies) | 104 if (node.dependencies) |
57 continue; | 105 continue; |
58 | 106 |
59 // Skip if already finished running task. | 107 // Skip if already finished running task. |
60 if (node.task->HasFinishedRunning()) | 108 if (node.task->HasFinishedRunning()) |
61 continue; | 109 continue; |
62 | 110 |
63 // Skip if already running. | 111 // Skip if already running. |
64 if (std::find(task_namespace.running_tasks.begin(), | 112 if (std::find(task_namespace.running_tasks.begin(), |
65 task_namespace.running_tasks.end(), | 113 task_namespace.running_tasks.end(), |
66 node.task) != task_namespace.running_tasks.end()) | 114 node.task) != task_namespace.running_tasks.end()) |
67 continue; | 115 continue; |
68 | 116 |
69 task_namespace.ready_to_run_tasks.push_back( | 117 task_namespace.ready_to_run_tasks[node.group].push_back( |
70 PrioritizedTask(node.task, &task_namespace, node.priority)); | 118 PrioritizedTask(node.task, &task_namespace, node.group, node.priority)); |
71 } | 119 } |
72 | 120 |
73 // Rearrange the elements in |ready_to_run_tasks| in such a way that they | 121 // Rearrange the elements in each vector within |ready_to_run_tasks| in such a |
74 // form a heap. | 122 // way that they form a heap. |
75 std::make_heap(task_namespace.ready_to_run_tasks.begin(), | 123 for (auto& vector : task_namespace.ready_to_run_tasks) { |
reveman
2015/12/04 02:30:54
nit: s/vector/ready_to_run_tasks/ not a fan of nam
ericrk
2015/12/04 19:14:30
Done.
| |
76 task_namespace.ready_to_run_tasks.end(), CompareTaskPriority); | 124 std::make_heap(vector.begin(), vector.end(), CompareTaskPriority); |
125 } | |
77 | 126 |
78 // Swap task graph. | 127 // Swap task graph. |
79 task_namespace.graph.Swap(graph); | 128 task_namespace.graph.Swap(graph); |
80 | 129 |
81 // Determine what tasks in old graph need to be canceled. | 130 // Determine what tasks in old graph need to be canceled. |
82 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin(); | 131 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin(); |
83 it != graph->nodes.end(); ++it) { | 132 it != graph->nodes.end(); ++it) { |
84 TaskGraph::Node& node = *it; | 133 TaskGraph::Node& node = *it; |
85 | 134 |
86 // Skip if already finished running task. | 135 // Skip if already finished running task. |
87 if (node.task->HasFinishedRunning()) | 136 if (node.task->HasFinishedRunning()) |
88 continue; | 137 continue; |
89 | 138 |
90 // Skip if already running. | 139 // Skip if already running. |
91 if (std::find(task_namespace.running_tasks.begin(), | 140 if (std::find(task_namespace.running_tasks.begin(), |
92 task_namespace.running_tasks.end(), | 141 task_namespace.running_tasks.end(), |
93 node.task) != task_namespace.running_tasks.end()) | 142 node.task) != task_namespace.running_tasks.end()) |
94 continue; | 143 continue; |
95 | 144 |
96 DCHECK(std::find(task_namespace.completed_tasks.begin(), | 145 DCHECK(std::find(task_namespace.completed_tasks.begin(), |
97 task_namespace.completed_tasks.end(), | 146 task_namespace.completed_tasks.end(), |
98 node.task) == task_namespace.completed_tasks.end()); | 147 node.task) == task_namespace.completed_tasks.end()); |
99 task_namespace.completed_tasks.push_back(node.task); | 148 task_namespace.completed_tasks.push_back(node.task); |
100 } | 149 } |
101 | 150 |
102 // Build new "ready to run" task namespaces queue. | 151 // Build new "ready to run" task namespaces queue. |
103 ready_to_run_namespaces_.clear(); | 152 ClearAllVectors(&ready_to_run_namespaces_); |
104 for (auto& it : namespaces_) { | 153 for (auto& it : namespaces_) { |
reveman
2015/12/04 02:30:53
would be nice if this could be something like:
fo
ericrk
2015/12/04 19:14:31
Couldn't do that before (when using an array), as
| |
105 if (!it.second.ready_to_run_tasks.empty()) | 154 for (uint16_t group = 0; group < kMaxTaskGroups; ++group) { |
106 ready_to_run_namespaces_.push_back(&it.second); | 155 if (!it.second.ready_to_run_tasks[group].empty()) |
156 ready_to_run_namespaces_[group].push_back(&it.second); | |
157 } | |
107 } | 158 } |
108 | 159 |
109 // Rearrange the task namespaces in |ready_to_run_namespaces| in such a | 160 // Rearrange the task namespaces in |ready_to_run_namespaces| in such a |
110 // way that they form a heap. | 161 // way that they form a heap. |
111 std::make_heap(ready_to_run_namespaces_.begin(), | 162 for (uint16_t group = 0; group < kMaxTaskGroups; ++group) { |
112 ready_to_run_namespaces_.end(), CompareTaskNamespacePriority); | 163 std::make_heap(ready_to_run_namespaces_[group].begin(), |
164 ready_to_run_namespaces_[group].end(), | |
165 CompareTaskNamespacePriority(group)); | |
166 } | |
113 } | 167 } |
114 | 168 |
115 TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() { | 169 TaskGraphWorkQueue::PrioritizedTask |
116 DCHECK(!ready_to_run_namespaces_.empty()); | 170 TaskGraphWorkQueue::GetNextTaskToRunForGroup(uint16_t group) { |
171 DCHECK(group < kMaxTaskGroups); | |
117 | 172 |
118 // Take top priority TaskNamespace from |ready_to_run_namespaces_|. | 173 TaskNamespace::Vector& namespaces_for_group = ready_to_run_namespaces_[group]; |
reveman
2015/12/04 02:30:54
nit: s/namespaces_for_group/ready_to_run_namespace
ericrk
2015/12/04 19:14:31
Done.
| |
119 std::pop_heap(ready_to_run_namespaces_.begin(), | 174 DCHECK(!namespaces_for_group.empty()); |
120 ready_to_run_namespaces_.end(), CompareTaskNamespacePriority); | |
121 TaskNamespace* task_namespace = ready_to_run_namespaces_.back(); | |
122 ready_to_run_namespaces_.pop_back(); | |
123 DCHECK(!task_namespace->ready_to_run_tasks.empty()); | |
124 | 175 |
125 // Take top priority task from |ready_to_run_tasks|. | 176 // Take top priority TaskNamespace from |namespaces_for_group|. |
126 std::pop_heap(task_namespace->ready_to_run_tasks.begin(), | 177 std::pop_heap(namespaces_for_group.begin(), namespaces_for_group.end(), |
127 task_namespace->ready_to_run_tasks.end(), CompareTaskPriority); | 178 CompareTaskNamespacePriority(group)); |
128 PrioritizedTask task = task_namespace->ready_to_run_tasks.back(); | 179 TaskNamespace* task_namespace = namespaces_for_group.back(); |
129 task_namespace->ready_to_run_tasks.pop_back(); | 180 namespaces_for_group.pop_back(); |
130 | 181 |
131 // Add task namespace back to |ready_to_run_namespaces_| if not empty after | 182 PrioritizedTask::Vector& tasks_for_group = |
reveman
2015/12/04 02:30:54
nit: s/tasks_for_group/ready_to_run_tasks_for_grou
ericrk
2015/12/04 19:14:30
Done.
| |
183 task_namespace->ready_to_run_tasks[group]; | |
184 DCHECK(!tasks_for_group.empty()); | |
185 | |
186 // Take top priority task from |tasks_for_group|. | |
187 std::pop_heap(tasks_for_group.begin(), tasks_for_group.end(), | |
188 CompareTaskPriority); | |
189 PrioritizedTask task = tasks_for_group.back(); | |
190 tasks_for_group.pop_back(); | |
191 | |
192 // Add task namespace back to |namespaces_for_group| if not empty after | |
132 // taking top priority task. | 193 // taking top priority task. |
133 if (!task_namespace->ready_to_run_tasks.empty()) { | 194 if (!tasks_for_group.empty()) { |
134 ready_to_run_namespaces_.push_back(task_namespace); | 195 namespaces_for_group.push_back(task_namespace); |
135 std::push_heap(ready_to_run_namespaces_.begin(), | 196 std::push_heap(namespaces_for_group.begin(), namespaces_for_group.end(), |
136 ready_to_run_namespaces_.end(), | 197 CompareTaskNamespacePriority(group)); |
137 CompareTaskNamespacePriority); | |
138 } | 198 } |
139 | 199 |
140 // Add task to |running_tasks|. | 200 // Add task to |running_tasks|. |
141 task_namespace->running_tasks.push_back(task.task); | 201 task_namespace->running_tasks.push_back(task.task); |
142 | 202 |
143 return task; | 203 return task; |
144 } | 204 } |
145 | 205 |
206 TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() { | |
207 for (uint16_t group = 0; group < kMaxTaskGroups; ++group) { | |
208 if (!ready_to_run_namespaces_[group].empty()) { | |
209 return GetNextTaskToRunForGroup(group); | |
210 } | |
211 } | |
212 | |
213 // This function must only be called when there is at least one task to run. | |
214 NOTREACHED(); | |
215 return GetNextTaskToRunForGroup(0); | |
216 } | |
217 | |
146 void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) { | 218 void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) { |
147 TaskNamespace* task_namespace = completed_task.task_namespace; | 219 TaskNamespace* task_namespace = completed_task.task_namespace; |
148 scoped_refptr<Task> task(completed_task.task); | 220 scoped_refptr<Task> task(completed_task.task); |
149 | 221 |
150 // Remove task from |running_tasks|. | 222 // Remove task from |running_tasks|. |
151 auto it = std::find(task_namespace->running_tasks.begin(), | 223 auto it = std::find(task_namespace->running_tasks.begin(), |
152 task_namespace->running_tasks.end(), task); | 224 task_namespace->running_tasks.end(), task); |
153 DCHECK(it != task_namespace->running_tasks.end()); | 225 DCHECK(it != task_namespace->running_tasks.end()); |
154 std::swap(*it, task_namespace->running_tasks.back()); | 226 std::swap(*it, task_namespace->running_tasks.back()); |
155 task_namespace->running_tasks.pop_back(); | 227 task_namespace->running_tasks.pop_back(); |
156 | 228 |
157 // Now iterate over all dependents to decrement dependencies and check if they | 229 // Now iterate over all dependents to decrement dependencies and check if they |
158 // are ready to run. | 230 // are ready to run. |
159 bool ready_to_run_namespaces_has_heap_properties = true; | 231 bool ready_to_run_namespaces_has_heap_properties = true; |
160 for (DependentIterator it(&task_namespace->graph, task.get()); it; ++it) { | 232 for (DependentIterator it(&task_namespace->graph, task.get()); it; ++it) { |
161 TaskGraph::Node& dependent_node = *it; | 233 TaskGraph::Node& dependent_node = *it; |
162 | 234 |
163 DCHECK_LT(0u, dependent_node.dependencies); | 235 DCHECK_LT(0u, dependent_node.dependencies); |
164 dependent_node.dependencies--; | 236 dependent_node.dependencies--; |
165 // Task is ready if it has no dependencies. Add it to |ready_to_run_tasks_|. | 237 // Task is ready if it has no dependencies. Add it to |ready_to_run_tasks_|. |
166 if (!dependent_node.dependencies) { | 238 if (!dependent_node.dependencies) { |
167 bool was_empty = task_namespace->ready_to_run_tasks.empty(); | 239 PrioritizedTask::Vector& tasks_for_group = |
reveman
2015/12/04 02:30:53
nit: same as above, ready_to_run_tasks_for_group o
ericrk
2015/12/04 19:14:31
Done.
| |
168 task_namespace->ready_to_run_tasks.push_back(PrioritizedTask( | 240 task_namespace->ready_to_run_tasks[dependent_node.group]; |
169 dependent_node.task, task_namespace, dependent_node.priority)); | 241 |
170 std::push_heap(task_namespace->ready_to_run_tasks.begin(), | 242 bool was_empty = tasks_for_group.empty(); |
171 task_namespace->ready_to_run_tasks.end(), | 243 tasks_for_group.push_back( |
244 PrioritizedTask(dependent_node.task, task_namespace, | |
245 dependent_node.group, dependent_node.priority)); | |
246 std::push_heap(tasks_for_group.begin(), tasks_for_group.end(), | |
172 CompareTaskPriority); | 247 CompareTaskPriority); |
248 | |
173 // Task namespace is ready if it has at least one ready to run task. Add | 249 // Task namespace is ready if it has at least one ready to run task. Add |
174 // it to |ready_to_run_namespaces_| if it just become ready. | 250 // it to |ready_to_run_namespaces_| if it just become ready. |
175 if (was_empty) { | 251 if (was_empty) { |
176 DCHECK(std::find(ready_to_run_namespaces_.begin(), | 252 TaskNamespace::Vector& namespaces_for_group = |
reveman
2015/12/04 02:30:53
ditto
ericrk
2015/12/04 19:14:31
Done.
| |
177 ready_to_run_namespaces_.end(), | 253 ready_to_run_namespaces_[dependent_node.group]; |
178 task_namespace) == ready_to_run_namespaces_.end()); | 254 |
179 ready_to_run_namespaces_.push_back(task_namespace); | 255 DCHECK(std::find(namespaces_for_group.begin(), |
256 namespaces_for_group.end(), | |
257 task_namespace) == namespaces_for_group.end()); | |
258 namespaces_for_group.push_back(task_namespace); | |
180 } | 259 } |
181 ready_to_run_namespaces_has_heap_properties = false; | 260 ready_to_run_namespaces_has_heap_properties = false; |
182 } | 261 } |
183 } | 262 } |
184 | 263 |
185 // Rearrange the task namespaces in |ready_to_run_namespaces_| in such a way | 264 // Rearrange the task namespaces in |ready_to_run_namespaces_| in such a way |
186 // that they yet again form a heap. | 265 // that they yet again form a heap. |
187 if (!ready_to_run_namespaces_has_heap_properties) { | 266 if (!ready_to_run_namespaces_has_heap_properties) { |
188 std::make_heap(ready_to_run_namespaces_.begin(), | 267 for (uint16_t group = 0; group < kMaxTaskGroups; ++group) { |
189 ready_to_run_namespaces_.end(), | 268 std::make_heap(ready_to_run_namespaces_[group].begin(), |
190 CompareTaskNamespacePriority); | 269 ready_to_run_namespaces_[group].end(), |
270 CompareTaskNamespacePriority(group)); | |
271 } | |
191 } | 272 } |
192 | 273 |
193 // Finally add task to |completed_tasks_|. | 274 // Finally add task to |completed_tasks_|. |
194 task_namespace->completed_tasks.push_back(task); | 275 task_namespace->completed_tasks.push_back(task); |
195 } | 276 } |
196 | 277 |
197 void TaskGraphWorkQueue::CollectCompletedTasks(NamespaceToken token, | 278 void TaskGraphWorkQueue::CollectCompletedTasks(NamespaceToken token, |
198 Task::Vector* completed_tasks) { | 279 Task::Vector* completed_tasks) { |
199 TaskNamespaceMap::iterator it = namespaces_.find(token); | 280 TaskNamespaceMap::iterator it = namespaces_.find(token); |
200 if (it == namespaces_.end()) | 281 if (it == namespaces_.end()) |
201 return; | 282 return; |
202 | 283 |
203 TaskNamespace& task_namespace = it->second; | 284 TaskNamespace& task_namespace = it->second; |
204 | 285 |
205 DCHECK_EQ(0u, completed_tasks->size()); | 286 DCHECK_EQ(0u, completed_tasks->size()); |
206 completed_tasks->swap(task_namespace.completed_tasks); | 287 completed_tasks->swap(task_namespace.completed_tasks); |
207 if (!HasFinishedRunningTasksInNamespace(&task_namespace)) | 288 if (!HasFinishedRunningTasksInNamespace(&task_namespace)) |
208 return; | 289 return; |
209 | 290 |
210 // Remove namespace if finished running tasks. | 291 // Remove namespace if finished running tasks. |
211 DCHECK_EQ(0u, task_namespace.completed_tasks.size()); | 292 DCHECK_EQ(0u, task_namespace.completed_tasks.size()); |
212 DCHECK_EQ(0u, task_namespace.ready_to_run_tasks.size()); | 293 DCHECK(AllVectorsEmpty(task_namespace.ready_to_run_tasks)); |
213 DCHECK_EQ(0u, task_namespace.running_tasks.size()); | 294 DCHECK_EQ(0u, task_namespace.running_tasks.size()); |
214 namespaces_.erase(it); | 295 namespaces_.erase(it); |
215 } | 296 } |
216 | 297 |
298 bool TaskGraphWorkQueue::HasReadyToRunTasks() const { | |
299 return !AllVectorsEmpty(ready_to_run_namespaces_); | |
300 } | |
301 | |
302 bool TaskGraphWorkQueue::HasFinishedRunningTasksInNamespace( | |
303 const TaskNamespace* task_namespace) { | |
304 return task_namespace->running_tasks.empty() && | |
305 AllVectorsEmpty(task_namespace->ready_to_run_tasks); | |
306 } | |
307 | |
217 bool TaskGraphWorkQueue::DependencyMismatch(const TaskGraph* graph) { | 308 bool TaskGraphWorkQueue::DependencyMismatch(const TaskGraph* graph) { |
218 // Value storage will be 0-initialized. | 309 // Value storage will be 0-initialized. |
219 base::hash_map<const Task*, size_t> dependents; | 310 base::hash_map<const Task*, size_t> dependents; |
220 for (const TaskGraph::Edge& edge : graph->edges) | 311 for (const TaskGraph::Edge& edge : graph->edges) |
221 dependents[edge.dependent]++; | 312 dependents[edge.dependent]++; |
222 | 313 |
223 for (const TaskGraph::Node& node : graph->nodes) { | 314 for (const TaskGraph::Node& node : graph->nodes) { |
224 if (dependents[node.task] != node.dependencies) | 315 if (dependents[node.task] != node.dependencies) |
225 return true; | 316 return true; |
226 } | 317 } |
227 | 318 |
228 return false; | 319 return false; |
229 } | 320 } |
230 | 321 |
322 bool TaskGraphWorkQueue::ValidateGroups(const TaskGraph* graph) { | |
323 for (const TaskGraph::Node& node : graph->nodes) { | |
324 if (node.group >= kMaxTaskGroups) | |
325 return false; | |
326 } | |
327 return true; | |
328 } | |
329 | |
231 } // namespace cc | 330 } // namespace cc |
OLD | NEW |