| 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 |