Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: cc/raster/task_graph_work_queue.cc

Issue 1449133002: TaskGraphRunner refactor (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "cc/raster/task_graph_work_queue.h"
6
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/trace_event/trace_event.h"
11
12 namespace cc {
13
14 TaskGraphWorkQueue::TaskNamespace::TaskNamespace() {}
15
16 TaskGraphWorkQueue::TaskNamespace::~TaskNamespace() {}
17
18 TaskGraphWorkQueue::TaskGraphWorkQueue() {}
19 TaskGraphWorkQueue::~TaskGraphWorkQueue() {}
20
21 void TaskGraphWorkQueue::ScheduleTasks(NamespaceToken token, TaskGraph* graph) {
22 TaskNamespace& task_namespace = namespaces_[token];
23
24 // First adjust number of dependencies to reflect completed tasks.
25 for (const scoped_refptr<Task>& task : task_namespace.completed_tasks) {
26 for (DependentIterator node_it(graph, task.get()); node_it; ++node_it) {
27 TaskGraph::Node& node = *node_it;
28 DCHECK_LT(0u, node.dependencies);
29 node.dependencies--;
30 }
31 }
32
33 // Build new "ready to run" queue and remove nodes from old graph.
34 task_namespace.ready_to_run_tasks.clear();
35 for (const TaskGraph::Node& node : graph->nodes) {
36 // Remove any old nodes that are associated with this task. The result is
37 // that the old graph is left with all nodes not present in this graph,
38 // which we use below to determine what tasks need to be canceled.
39 TaskGraph::Node::Vector::iterator old_it = std::find_if(
40 task_namespace.graph.nodes.begin(), task_namespace.graph.nodes.end(),
41 [node](const TaskGraph::Node& other) {
42 return node.task == other.task;
43 });
44 if (old_it != task_namespace.graph.nodes.end()) {
45 std::swap(*old_it, task_namespace.graph.nodes.back());
46 task_namespace.graph.nodes.pop_back();
47 }
48
49 // Task is not ready to run if dependencies are not yet satisfied.
50 if (node.dependencies)
51 continue;
52
53 // Skip if already finished running task.
54 if (node.task->HasFinishedRunning())
55 continue;
56
57 // Skip if already running.
58 if (std::find(task_namespace.running_tasks.begin(),
59 task_namespace.running_tasks.end(),
60 node.task) != task_namespace.running_tasks.end())
61 continue;
62
63 task_namespace.ready_to_run_tasks.push_back(
64 PrioritizedTask(node.task, &task_namespace, node.priority));
65 }
66
67 // Rearrange the elements in |ready_to_run_tasks| in such a way that they
68 // form a heap.
69 std::make_heap(task_namespace.ready_to_run_tasks.begin(),
70 task_namespace.ready_to_run_tasks.end(), CompareTaskPriority);
71
72 // Swap task graph.
73 task_namespace.graph.Swap(graph);
74
75 // Determine what tasks in old graph need to be canceled.
76 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin();
77 it != graph->nodes.end(); ++it) {
78 TaskGraph::Node& node = *it;
79
80 // Skip if already finished running task.
81 if (node.task->HasFinishedRunning())
82 continue;
83
84 // Skip if already running.
85 if (std::find(task_namespace.running_tasks.begin(),
86 task_namespace.running_tasks.end(),
87 node.task) != task_namespace.running_tasks.end())
88 continue;
89
90 DCHECK(std::find(task_namespace.completed_tasks.begin(),
91 task_namespace.completed_tasks.end(),
92 node.task) == task_namespace.completed_tasks.end());
93 task_namespace.completed_tasks.push_back(node.task);
94 }
95
96 // Build new "ready to run" task namespaces queue.
97 ready_to_run_namespaces_.clear();
98 for (auto& it : namespaces_) {
99 if (!it.second.ready_to_run_tasks.empty())
100 ready_to_run_namespaces_.push_back(&it.second);
101 }
102
103 // Rearrange the task namespaces in |ready_to_run_namespaces| in such a
104 // way that they form a heap.
105 std::make_heap(ready_to_run_namespaces_.begin(),
106 ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
107 }
108
109 TaskGraphWorkQueue::PrioritizedTask TaskGraphWorkQueue::GetNextTaskToRun() {
110 DCHECK(!ready_to_run_namespaces_.empty());
111
112 // Take top priority TaskNamespace from |ready_to_run_namespaces_|.
113 std::pop_heap(ready_to_run_namespaces_.begin(),
114 ready_to_run_namespaces_.end(), CompareTaskNamespacePriority);
115 TaskNamespace* task_namespace = ready_to_run_namespaces_.back();
116 ready_to_run_namespaces_.pop_back();
117 DCHECK(!task_namespace->ready_to_run_tasks.empty());
118
119 // Take top priority task from |ready_to_run_tasks|.
120 std::pop_heap(task_namespace->ready_to_run_tasks.begin(),
121 task_namespace->ready_to_run_tasks.end(), CompareTaskPriority);
122 PrioritizedTask task = task_namespace->ready_to_run_tasks.back();
123 task_namespace->ready_to_run_tasks.pop_back();
124
125 // Add task namespace back to |ready_to_run_namespaces_| if not empty after
126 // taking top priority task.
127 if (!task_namespace->ready_to_run_tasks.empty()) {
128 ready_to_run_namespaces_.push_back(task_namespace);
129 std::push_heap(ready_to_run_namespaces_.begin(),
130 ready_to_run_namespaces_.end(),
131 CompareTaskNamespacePriority);
132 }
133
134 // Add task to |running_tasks|.
135 task_namespace->running_tasks.push_back(task.task);
136
137 return task;
138 }
139
140 void TaskGraphWorkQueue::CompleteTask(const PrioritizedTask& completed_task) {
141 TaskNamespace* task_namespace = completed_task.task_namespace;
142 Task* task = completed_task.task;
143
144 // Remove task from |running_tasks|.
145 auto it = std::find(task_namespace->running_tasks.begin(),
146 task_namespace->running_tasks.end(), task);
147 DCHECK(it != task_namespace->running_tasks.end());
148 std::swap(*it, task_namespace->running_tasks.back());
149 task_namespace->running_tasks.pop_back();
150
151 // Now iterate over all dependents to decrement dependencies and check if they
152 // are ready to run.
153 bool ready_to_run_namespaces_has_heap_properties = true;
154 for (DependentIterator it(&task_namespace->graph, task); it; ++it) {
155 TaskGraph::Node& dependent_node = *it;
156
157 DCHECK_LT(0u, dependent_node.dependencies);
158 dependent_node.dependencies--;
159 // Task is ready if it has no dependencies. Add it to |ready_to_run_tasks_|.
160 if (!dependent_node.dependencies) {
161 bool was_empty = task_namespace->ready_to_run_tasks.empty();
162 task_namespace->ready_to_run_tasks.push_back(PrioritizedTask(
163 dependent_node.task, task_namespace, dependent_node.priority));
164 std::push_heap(task_namespace->ready_to_run_tasks.begin(),
165 task_namespace->ready_to_run_tasks.end(),
166 CompareTaskPriority);
167 // Task namespace is ready if it has at least one ready to run task. Add
168 // it to |ready_to_run_namespaces_| if it just become ready.
169 if (was_empty) {
170 DCHECK(std::find(ready_to_run_namespaces_.begin(),
171 ready_to_run_namespaces_.end(),
172 task_namespace) == ready_to_run_namespaces_.end());
173 ready_to_run_namespaces_.push_back(task_namespace);
174 }
175 ready_to_run_namespaces_has_heap_properties = false;
176 }
177 }
178
179 // Rearrange the task namespaces in |ready_to_run_namespaces_| in such a way
180 // that they yet again form a heap.
181 if (!ready_to_run_namespaces_has_heap_properties) {
182 std::make_heap(ready_to_run_namespaces_.begin(),
183 ready_to_run_namespaces_.end(),
184 CompareTaskNamespacePriority);
185 }
186
187 // Finally add task to |completed_tasks_|.
188 task_namespace->completed_tasks.push_back(task);
189 }
190
191 void TaskGraphWorkQueue::CollectCompletedTasks(NamespaceToken token,
192 Task::Vector* completed_tasks) {
193 TaskNamespaceMap::iterator it = namespaces_.find(token);
194 if (it == namespaces_.end())
195 return;
196
197 TaskNamespace& task_namespace = it->second;
198
199 DCHECK_EQ(0u, completed_tasks->size());
200 completed_tasks->swap(task_namespace.completed_tasks);
201 if (!HasFinishedRunningTasksInNamespace(&task_namespace))
202 return;
203
204 // Remove namespace if finished running tasks.
205 DCHECK_EQ(0u, task_namespace.completed_tasks.size());
206 DCHECK_EQ(0u, task_namespace.ready_to_run_tasks.size());
207 DCHECK_EQ(0u, task_namespace.running_tasks.size());
208 // namespaces_.erase(it);
209 }
210
211 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698