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

Side by Side Diff: cc/resources/task_graph_runner.cc

Issue 131543014: cc: Use std::map instead of hash_map for TaskGraphRunner namespaces. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 months 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 | Annotate | Revision Log
« no previous file with comments | « cc/resources/task_graph_runner.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/resources/task_graph_runner.h" 5 #include "cc/resources/task_graph_runner.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/strings/stringprintf.h" 10 #include "base/strings/stringprintf.h"
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 } 158 }
159 159
160 void TaskGraphRunner::WaitForTasksToFinishRunning(NamespaceToken token) { 160 void TaskGraphRunner::WaitForTasksToFinishRunning(NamespaceToken token) {
161 TRACE_EVENT0("cc", "TaskGraphRunner::WaitForTasksToFinishRunning"); 161 TRACE_EVENT0("cc", "TaskGraphRunner::WaitForTasksToFinishRunning");
162 162
163 DCHECK(token.IsValid()); 163 DCHECK(token.IsValid());
164 164
165 { 165 {
166 base::AutoLock lock(lock_); 166 base::AutoLock lock(lock_);
167 167
168 TaskNamespaceMap::iterator it = namespaces_.find(token.id_); 168 TaskNamespaceMap::const_iterator it = namespaces_.find(token.id_);
169 if (it == namespaces_.end()) 169 if (it == namespaces_.end())
170 return; 170 return;
171 171
172 TaskNamespace* task_namespace = it->second; 172 const TaskNamespace& task_namespace = it->second;
173 173
174 while (!HasFinishedRunningTasksInNamespace(task_namespace)) 174 while (!HasFinishedRunningTasksInNamespace(&task_namespace))
175 has_namespaces_with_finished_running_tasks_cv_.Wait(); 175 has_namespaces_with_finished_running_tasks_cv_.Wait();
176 176
177 // There may be other namespaces that have finished running 177 // There may be other namespaces that have finished running
178 // tasks, so wake up another origin thread. 178 // tasks, so wake up another origin thread.
179 has_namespaces_with_finished_running_tasks_cv_.Signal(); 179 has_namespaces_with_finished_running_tasks_cv_.Signal();
180 } 180 }
181 } 181 }
182 182
183 void TaskGraphRunner::SetTaskGraph(NamespaceToken token, TaskGraph* graph) { 183 void TaskGraphRunner::SetTaskGraph(NamespaceToken token, TaskGraph* graph) {
184 TRACE_EVENT2("cc", 184 TRACE_EVENT2("cc",
185 "TaskGraphRunner::SetTaskGraph", 185 "TaskGraphRunner::SetTaskGraph",
186 "num_nodes", 186 "num_nodes",
187 graph->nodes.size(), 187 graph->nodes.size(),
188 "num_edges", 188 "num_edges",
189 graph->edges.size()); 189 graph->edges.size());
190 190
191 DCHECK(token.IsValid()); 191 DCHECK(token.IsValid());
192 192
193 { 193 {
194 base::AutoLock lock(lock_); 194 base::AutoLock lock(lock_);
195 195
196 DCHECK(!shutdown_); 196 DCHECK(!shutdown_);
197 197
198 scoped_ptr<TaskNamespace> task_namespace = 198 TaskNamespace& task_namespace = namespaces_[token.id_];
199 namespaces_.take_and_erase(token.id_);
200
201 // Create task namespace if it doesn't exist.
202 if (!task_namespace)
203 task_namespace.reset(new TaskNamespace);
204 199
205 // First adjust number of dependencies to reflect completed tasks. 200 // First adjust number of dependencies to reflect completed tasks.
206 for (Task::Vector::iterator it = task_namespace->completed_tasks.begin(); 201 for (Task::Vector::iterator it = task_namespace.completed_tasks.begin();
207 it != task_namespace->completed_tasks.end(); 202 it != task_namespace.completed_tasks.end();
208 ++it) { 203 ++it) {
209 for (DependentIterator node_it(graph, it->get()); node_it; ++node_it) { 204 for (DependentIterator node_it(graph, it->get()); node_it; ++node_it) {
210 TaskGraph::Node& node = *node_it; 205 TaskGraph::Node& node = *node_it;
211 DCHECK_LT(0u, node.dependencies); 206 DCHECK_LT(0u, node.dependencies);
212 node.dependencies--; 207 node.dependencies--;
213 } 208 }
214 } 209 }
215 210
216 // Build new "ready to run" queue and remove nodes from old graph. 211 // Build new "ready to run" queue and remove nodes from old graph.
217 task_namespace->ready_to_run_tasks.clear(); 212 task_namespace.ready_to_run_tasks.clear();
218 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin(); 213 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin();
219 it != graph->nodes.end(); 214 it != graph->nodes.end();
220 ++it) { 215 ++it) {
221 TaskGraph::Node& node = *it; 216 TaskGraph::Node& node = *it;
222 217
223 // Remove any old nodes that are associated with this task. The result is 218 // Remove any old nodes that are associated with this task. The result is
224 // that the old graph is left all nodes not present in this graph, which 219 // that the old graph is left all nodes not present in this graph, which
225 // we use below to determine what tasks need to be canceled. 220 // we use below to determine what tasks need to be canceled.
226 TaskGraph::Node::Vector::iterator old_it = 221 TaskGraph::Node::Vector::iterator old_it =
227 std::find_if(task_namespace->graph.nodes.begin(), 222 std::find_if(task_namespace.graph.nodes.begin(),
228 task_namespace->graph.nodes.end(), 223 task_namespace.graph.nodes.end(),
229 TaskGraph::Node::TaskComparator(node.task)); 224 TaskGraph::Node::TaskComparator(node.task));
230 if (old_it != task_namespace->graph.nodes.end()) { 225 if (old_it != task_namespace.graph.nodes.end()) {
231 std::swap(*old_it, task_namespace->graph.nodes.back()); 226 std::swap(*old_it, task_namespace.graph.nodes.back());
232 task_namespace->graph.nodes.pop_back(); 227 task_namespace.graph.nodes.pop_back();
233 } 228 }
234 229
235 // Task is not ready to run if dependencies are not yet satisfied. 230 // Task is not ready to run if dependencies are not yet satisfied.
236 if (node.dependencies) 231 if (node.dependencies)
237 continue; 232 continue;
238 233
239 // Skip if already finished running task. 234 // Skip if already finished running task.
240 if (node.task->HasFinishedRunning()) 235 if (node.task->HasFinishedRunning())
241 continue; 236 continue;
242 237
243 // Skip if already running. 238 // Skip if already running.
244 if (std::find(running_tasks_.begin(), running_tasks_.end(), node.task) != 239 if (std::find(running_tasks_.begin(), running_tasks_.end(), node.task) !=
245 running_tasks_.end()) 240 running_tasks_.end())
246 continue; 241 continue;
247 242
248 task_namespace->ready_to_run_tasks.push_back( 243 task_namespace.ready_to_run_tasks.push_back(
249 PrioritizedTask(node.task, node.priority)); 244 PrioritizedTask(node.task, node.priority));
250 } 245 }
251 246
252 // Rearrange the elements in |ready_to_run_tasks| in such a way that 247 // Rearrange the elements in |ready_to_run_tasks| in such a way that
253 // they form a heap. 248 // they form a heap.
254 std::make_heap(task_namespace->ready_to_run_tasks.begin(), 249 std::make_heap(task_namespace.ready_to_run_tasks.begin(),
255 task_namespace->ready_to_run_tasks.end(), 250 task_namespace.ready_to_run_tasks.end(),
256 CompareTaskPriority); 251 CompareTaskPriority);
257 252
258 // Swap task graph. 253 // Swap task graph.
259 task_namespace->graph.Swap(graph); 254 task_namespace.graph.Swap(graph);
260 255
261 // Determine what tasks in old graph need to be canceled. 256 // Determine what tasks in old graph need to be canceled.
262 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin(); 257 for (TaskGraph::Node::Vector::iterator it = graph->nodes.begin();
263 it != graph->nodes.end(); 258 it != graph->nodes.end();
264 ++it) { 259 ++it) {
265 TaskGraph::Node& node = *it; 260 TaskGraph::Node& node = *it;
266 261
267 // Skip if already finished running task. 262 // Skip if already finished running task.
268 if (node.task->HasFinishedRunning()) 263 if (node.task->HasFinishedRunning())
269 continue; 264 continue;
270 265
271 // Skip if already running. 266 // Skip if already running.
272 if (std::find(running_tasks_.begin(), running_tasks_.end(), node.task) != 267 if (std::find(running_tasks_.begin(), running_tasks_.end(), node.task) !=
273 running_tasks_.end()) 268 running_tasks_.end())
274 continue; 269 continue;
275 270
276 task_namespace->completed_tasks.push_back(node.task); 271 task_namespace.completed_tasks.push_back(node.task);
277 } 272 }
278 273
279 namespaces_.set(token.id_, task_namespace.Pass());
280
281 // Build new "ready to run" task namespaces queue. 274 // Build new "ready to run" task namespaces queue.
282 ready_to_run_namespaces_.clear(); 275 ready_to_run_namespaces_.clear();
283 for (TaskNamespaceMap::iterator it = namespaces_.begin(); 276 for (TaskNamespaceMap::iterator it = namespaces_.begin();
284 it != namespaces_.end(); 277 it != namespaces_.end();
285 ++it) { 278 ++it) {
286 if (!it->second->ready_to_run_tasks.empty()) 279 if (!it->second.ready_to_run_tasks.empty())
287 ready_to_run_namespaces_.push_back(it->second); 280 ready_to_run_namespaces_.push_back(&it->second);
288 } 281 }
289 282
290 // Rearrange the task namespaces in |ready_to_run_namespaces_| 283 // Rearrange the task namespaces in |ready_to_run_namespaces_|
291 // in such a way that they form a heap. 284 // in such a way that they form a heap.
292 std::make_heap(ready_to_run_namespaces_.begin(), 285 std::make_heap(ready_to_run_namespaces_.begin(),
293 ready_to_run_namespaces_.end(), 286 ready_to_run_namespaces_.end(),
294 CompareTaskNamespacePriority); 287 CompareTaskNamespacePriority);
295 288
296 // If there is more work available, wake up worker thread. 289 // If there is more work available, wake up worker thread.
297 if (!ready_to_run_namespaces_.empty()) 290 if (!ready_to_run_namespaces_.empty())
298 has_ready_to_run_tasks_cv_.Signal(); 291 has_ready_to_run_tasks_cv_.Signal();
299 } 292 }
300 } 293 }
301 294
302 void TaskGraphRunner::CollectCompletedTasks(NamespaceToken token, 295 void TaskGraphRunner::CollectCompletedTasks(NamespaceToken token,
303 Task::Vector* completed_tasks) { 296 Task::Vector* completed_tasks) {
304 TRACE_EVENT0("cc", "TaskGraphRunner::CollectCompletedTasks"); 297 TRACE_EVENT0("cc", "TaskGraphRunner::CollectCompletedTasks");
305 298
306 DCHECK(token.IsValid()); 299 DCHECK(token.IsValid());
307 300
308 { 301 {
309 base::AutoLock lock(lock_); 302 base::AutoLock lock(lock_);
310 303
311 TaskNamespaceMap::iterator it = namespaces_.find(token.id_); 304 TaskNamespaceMap::iterator it = namespaces_.find(token.id_);
312 if (it == namespaces_.end()) 305 if (it == namespaces_.end())
313 return; 306 return;
314 307
315 TaskNamespace* task_namespace = it->second; 308 TaskNamespace& task_namespace = it->second;
316 309
317 DCHECK_EQ(0u, completed_tasks->size()); 310 DCHECK_EQ(0u, completed_tasks->size());
318 completed_tasks->swap(task_namespace->completed_tasks); 311 completed_tasks->swap(task_namespace.completed_tasks);
319 if (!HasFinishedRunningTasksInNamespace(task_namespace)) 312 if (!HasFinishedRunningTasksInNamespace(&task_namespace))
320 return; 313 return;
321 314
322 // Remove namespace if finished running tasks. 315 // Remove namespace if finished running tasks.
323 DCHECK_EQ(0u, task_namespace->completed_tasks.size()); 316 DCHECK_EQ(0u, task_namespace.completed_tasks.size());
324 DCHECK_EQ(0u, task_namespace->ready_to_run_tasks.size()); 317 DCHECK_EQ(0u, task_namespace.ready_to_run_tasks.size());
325 DCHECK_EQ(0u, task_namespace->num_running_tasks); 318 DCHECK_EQ(0u, task_namespace.num_running_tasks);
326 namespaces_.erase(it); 319 namespaces_.erase(it);
327 } 320 }
328 } 321 }
329 322
330 bool TaskGraphRunner::RunTaskForTesting() { 323 bool TaskGraphRunner::RunTaskForTesting() {
331 base::AutoLock lock(lock_); 324 base::AutoLock lock(lock_);
332 325
333 if (ready_to_run_namespaces_.empty()) 326 if (ready_to_run_namespaces_.empty())
334 return false; 327 return false;
335 328
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 // Finally add task to |completed_tasks_|. 454 // Finally add task to |completed_tasks_|.
462 task_namespace->completed_tasks.push_back(task); 455 task_namespace->completed_tasks.push_back(task);
463 456
464 // If namespace has finished running all tasks, wake up origin thread. 457 // If namespace has finished running all tasks, wake up origin thread.
465 if (HasFinishedRunningTasksInNamespace(task_namespace)) 458 if (HasFinishedRunningTasksInNamespace(task_namespace))
466 has_namespaces_with_finished_running_tasks_cv_.Signal(); 459 has_namespaces_with_finished_running_tasks_cv_.Signal();
467 } 460 }
468 461
469 } // namespace internal 462 } // namespace internal
470 } // namespace cc 463 } // namespace cc
OLDNEW
« no previous file with comments | « cc/resources/task_graph_runner.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698