OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/worker_pool.h" | 5 #include "cc/resources/worker_pool.h" |
6 | 6 |
7 #if defined(OS_ANDROID) | 7 #if defined(OS_ANDROID) |
8 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) | 8 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) |
9 #include <sys/resource.h> | 9 #include <sys/resource.h> |
10 #endif | 10 #endif |
(...skipping 11 matching lines...) Expand all Loading... |
22 namespace cc { | 22 namespace cc { |
23 | 23 |
24 namespace internal { | 24 namespace internal { |
25 | 25 |
26 WorkerPoolTask::WorkerPoolTask() | 26 WorkerPoolTask::WorkerPoolTask() |
27 : did_schedule_(false), | 27 : did_schedule_(false), |
28 did_run_(false), | 28 did_run_(false), |
29 did_complete_(false) { | 29 did_complete_(false) { |
30 } | 30 } |
31 | 31 |
32 WorkerPoolTask::WorkerPoolTask(TaskVector* dependencies) | |
33 : did_schedule_(false), | |
34 did_run_(false), | |
35 did_complete_(false) { | |
36 dependencies_.swap(*dependencies); | |
37 } | |
38 | |
39 WorkerPoolTask::~WorkerPoolTask() { | 32 WorkerPoolTask::~WorkerPoolTask() { |
40 DCHECK_EQ(did_schedule_, did_complete_); | 33 DCHECK_EQ(did_schedule_, did_complete_); |
41 DCHECK(!did_run_ || did_schedule_); | 34 DCHECK(!did_run_ || did_schedule_); |
42 DCHECK(!did_run_ || did_complete_); | 35 DCHECK(!did_run_ || did_complete_); |
43 } | 36 } |
44 | 37 |
45 void WorkerPoolTask::DidSchedule() { | 38 void WorkerPoolTask::DidSchedule() { |
46 DCHECK(!did_complete_); | 39 DCHECK(!did_complete_); |
47 did_schedule_ = true; | 40 did_schedule_ = true; |
48 } | 41 } |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 // NULL if |new_pending_tasks| doesn't contain task. This does | 228 // NULL if |new_pending_tasks| doesn't contain task. This does |
236 // the right in both cases. | 229 // the right in both cases. |
237 new_running_tasks.set(task, new_pending_tasks.take_and_erase(task)); | 230 new_running_tasks.set(task, new_pending_tasks.take_and_erase(task)); |
238 } | 231 } |
239 | 232 |
240 // Build new "ready to run" tasks queue. | 233 // Build new "ready to run" tasks queue. |
241 // TODO(reveman): Create this queue when building the task graph instead. | 234 // TODO(reveman): Create this queue when building the task graph instead. |
242 for (GraphNodeMap::iterator it = new_pending_tasks.begin(); | 235 for (GraphNodeMap::iterator it = new_pending_tasks.begin(); |
243 it != new_pending_tasks.end(); ++it) { | 236 it != new_pending_tasks.end(); ++it) { |
244 internal::WorkerPoolTask* task = it->first; | 237 internal::WorkerPoolTask* task = it->first; |
| 238 DCHECK(task); |
245 GraphNode* node = it->second; | 239 GraphNode* node = it->second; |
246 | 240 |
247 // Completed tasks should not exist in |new_pending_tasks|. | 241 // Completed tasks should not exist in |new_pending_tasks|. |
248 DCHECK(!task->HasFinishedRunning()); | 242 DCHECK(!task->HasFinishedRunning()); |
249 | 243 |
250 // Call DidSchedule() to indicate that this task has been scheduled. | 244 // Call DidSchedule() to indicate that this task has been scheduled. |
251 // Note: This is only for debugging purposes. | 245 // Note: This is only for debugging purposes. |
252 task->DidSchedule(); | 246 task->DidSchedule(); |
253 | 247 |
254 DCHECK_EQ(0u, new_ready_to_run_tasks.count(node->priority())); | 248 DCHECK_EQ(0u, new_ready_to_run_tasks.count(node->priority())); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
352 | 346 |
353 // Finally add task to |completed_tasks_|. | 347 // Finally add task to |completed_tasks_|. |
354 completed_tasks_.push_back(task); | 348 completed_tasks_.push_back(task); |
355 } | 349 } |
356 | 350 |
357 // We noticed we should exit. Wake up the next worker so it knows it should | 351 // We noticed we should exit. Wake up the next worker so it knows it should |
358 // exit as well (because the Shutdown() code only signals once). | 352 // exit as well (because the Shutdown() code only signals once). |
359 has_ready_to_run_tasks_cv_.Signal(); | 353 has_ready_to_run_tasks_cv_.Signal(); |
360 } | 354 } |
361 | 355 |
362 WorkerPool::GraphNode::GraphNode(internal::WorkerPoolTask* task) | 356 WorkerPool::GraphNode::GraphNode() |
363 : task_(task), | 357 : task_(NULL), |
364 priority_(0), | 358 priority_(0), |
365 num_dependencies_(0) { | 359 num_dependencies_(0) { |
366 } | 360 } |
367 | 361 |
368 WorkerPool::GraphNode::~GraphNode() { | 362 WorkerPool::GraphNode::~GraphNode() { |
369 } | 363 } |
370 | 364 |
371 WorkerPool::WorkerPool(size_t num_threads, | 365 WorkerPool::WorkerPool(size_t num_threads, |
372 const std::string& thread_name_prefix) | 366 const std::string& thread_name_prefix) |
373 : in_dispatch_completion_callbacks_(false), | 367 : in_dispatch_completion_callbacks_(false), |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 task->DidComplete(); | 401 task->DidComplete(); |
408 task->DispatchCompletionCallback(); | 402 task->DispatchCompletionCallback(); |
409 | 403 |
410 completed_tasks->pop_front(); | 404 completed_tasks->pop_front(); |
411 } | 405 } |
412 | 406 |
413 in_dispatch_completion_callbacks_ = false; | 407 in_dispatch_completion_callbacks_ = false; |
414 } | 408 } |
415 | 409 |
416 void WorkerPool::SetTaskGraph(TaskGraph* graph) { | 410 void WorkerPool::SetTaskGraph(TaskGraph* graph) { |
417 TRACE_EVENT0("cc", "WorkerPool::SetTaskGraph"); | 411 TRACE_EVENT1("cc", "WorkerPool::SetTaskGraph", |
| 412 "num_tasks", graph->size()); |
418 | 413 |
419 DCHECK(!in_dispatch_completion_callbacks_); | 414 DCHECK(!in_dispatch_completion_callbacks_); |
420 | 415 |
421 inner_->SetTaskGraph(graph); | 416 inner_->SetTaskGraph(graph); |
422 } | 417 } |
423 | 418 |
424 // static | |
425 unsigned WorkerPool::BuildTaskGraphRecursive( | |
426 internal::WorkerPoolTask* task, | |
427 GraphNode* dependent, | |
428 unsigned priority, | |
429 TaskGraph* graph) { | |
430 GraphNodeMap::iterator it = graph->find(task); | |
431 if (it != graph->end()) { | |
432 GraphNode* node = it->second; | |
433 node->add_dependent(dependent); | |
434 return priority; | |
435 } | |
436 | |
437 scoped_ptr<GraphNode> node(new GraphNode(task)); | |
438 | |
439 typedef internal::WorkerPoolTask::TaskVector TaskVector; | |
440 for (TaskVector::iterator dependency_it = task->dependencies().begin(); | |
441 dependency_it != task->dependencies().end(); ++dependency_it) { | |
442 internal::WorkerPoolTask* dependency = dependency_it->get(); | |
443 // Skip sub-tree if task has already completed. | |
444 if (dependency->HasCompleted()) | |
445 continue; | |
446 | |
447 node->add_dependency(); | |
448 | |
449 priority = BuildTaskGraphRecursive(dependency, | |
450 node.get(), | |
451 priority, | |
452 graph); | |
453 } | |
454 | |
455 node->set_priority(priority); | |
456 if (dependent) | |
457 node->add_dependent(dependent); | |
458 | |
459 graph->set(task, node.Pass()); | |
460 | |
461 return priority + 1; | |
462 } | |
463 | |
464 // static | |
465 void WorkerPool::BuildTaskGraph( | |
466 internal::WorkerPoolTask* root, TaskGraph* graph) { | |
467 const unsigned kBasePriority = 0u; | |
468 if (root && !root->HasCompleted()) | |
469 BuildTaskGraphRecursive(root, NULL, kBasePriority, graph); | |
470 } | |
471 | |
472 } // namespace cc | 419 } // namespace cc |
OLD | NEW |