Index: content/renderer/raster_worker_pool.cc |
diff --git a/content/renderer/raster_worker_pool.cc b/content/renderer/raster_worker_pool.cc |
index 6f5687e8cf2113b3e80ecfbfdaa0f15d623daad9..b8b13cdeff9edc900f19246d262ac1d172f8d05d 100644 |
--- a/content/renderer/raster_worker_pool.cc |
+++ b/content/renderer/raster_worker_pool.cc |
@@ -5,6 +5,8 @@ |
#include "content/renderer/raster_worker_pool.h" |
#include "base/strings/stringprintf.h" |
+#include "base/threading/thread_restrictions.h" |
+#include "base/trace_event/trace_event.h" |
namespace content { |
@@ -12,7 +14,8 @@ namespace content { |
class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner |
: public base::SequencedTaskRunner { |
public: |
- RasterWorkerPoolSequencedTaskRunner(cc::TaskGraphRunner* task_graph_runner) |
+ explicit RasterWorkerPoolSequencedTaskRunner( |
+ cc::TaskGraphRunner* task_graph_runner) |
: task_graph_runner_(task_graph_runner), |
namespace_token_(task_graph_runner->GetNamespaceToken()) {} |
@@ -63,11 +66,11 @@ class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner |
&completed_tasks_); |
}; |
- cc::TaskGraphRunner* const task_graph_runner_; |
- |
// Lock to exclusively access all the following members that are used to |
// implement the SequencedTaskRunner interfaces. |
base::Lock lock_; |
+ |
+ cc::TaskGraphRunner* task_graph_runner_; |
// Namespace used to schedule tasks in the task graph runner. |
cc::NamespaceToken namespace_token_; |
// List of tasks currently queued up for execution. |
@@ -80,7 +83,10 @@ class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner |
}; |
RasterWorkerPool::RasterWorkerPool() |
- : namespace_token_(task_graph_runner_.GetNamespaceToken()) {} |
+ : namespace_token_(GetNamespaceToken()), |
+ has_ready_to_run_tasks_cv_(&lock_), |
+ has_namespaces_with_finished_running_tasks_cv_(&lock_), |
+ shutdown_(false) {} |
void RasterWorkerPool::Start( |
int num_threads, |
@@ -99,10 +105,22 @@ void RasterWorkerPool::Start( |
} |
void RasterWorkerPool::Shutdown() { |
- task_graph_runner_.WaitForTasksToFinishRunning(namespace_token_); |
- task_graph_runner_.CollectCompletedTasks(namespace_token_, &completed_tasks_); |
+ WaitForTasksToFinishRunning(namespace_token_); |
+ CollectCompletedTasks(namespace_token_, &completed_tasks_); |
// Shutdown raster threads. |
- task_graph_runner_.Shutdown(); |
+ { |
+ base::AutoLock lock(lock_); |
+ |
+ DCHECK(!work_queue_.HasReadyToRunTasks()); |
+ DCHECK(!work_queue_.HasAnyNamespaces()); |
+ |
+ DCHECK(!shutdown_); |
+ shutdown_ = true; |
+ |
+ // Wake up a worker so it knows it should exit. This will cause all workers |
+ // to exit as each will wake up another worker before exiting. |
+ has_ready_to_run_tasks_cv_.Signal(); |
+ } |
while (!threads_.empty()) { |
threads_.back()->Join(); |
threads_.pop_back(); |
@@ -118,7 +136,7 @@ bool RasterWorkerPool::PostDelayedTask( |
// Remove completed tasks. |
DCHECK(completed_tasks_.empty()); |
- task_graph_runner_.CollectCompletedTasks(namespace_token_, &completed_tasks_); |
+ CollectCompletedTasksWithLockAcquired(namespace_token_, &completed_tasks_); |
cc::Task::Vector::iterator end = std::remove_if( |
tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) { |
@@ -133,7 +151,7 @@ bool RasterWorkerPool::PostDelayedTask( |
for (const auto& graph_task : tasks_) |
graph_.nodes.push_back(cc::TaskGraph::Node(graph_task.get(), 0, 0)); |
- task_graph_runner_.ScheduleTasks(namespace_token_, &graph_); |
+ ScheduleTasksWithLockAcquired(namespace_token_, &graph_); |
completed_tasks_.clear(); |
return true; |
} |
@@ -144,16 +162,142 @@ bool RasterWorkerPool::RunsTasksOnCurrentThread() const { |
// Overridden from base::DelegateSimpleThread::Delegate: |
void RasterWorkerPool::Run() { |
- task_graph_runner_.Run(); |
+ base::AutoLock lock(lock_); |
+ |
+ while (true) { |
+ if (!work_queue_.HasReadyToRunTasks()) { |
+ // Exit when shutdown is set and no more tasks are pending. |
+ if (shutdown_) |
+ break; |
+ |
+ // Wait for more tasks. |
+ has_ready_to_run_tasks_cv_.Wait(); |
+ continue; |
+ } |
+ |
+ RunTaskWithLockAcquired(); |
+ } |
+ |
+ // We noticed we should exit. Wake up the next worker so it knows it should |
+ // exit as well (because the Shutdown() code only signals once). |
+ has_ready_to_run_tasks_cv_.Signal(); |
+} |
+ |
+void RasterWorkerPool::FlushForTesting() { |
+ base::AutoLock lock(lock_); |
+ |
+ while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) { |
+ has_namespaces_with_finished_running_tasks_cv_.Wait(); |
+ } |
} |
scoped_refptr<base::SequencedTaskRunner> |
RasterWorkerPool::CreateSequencedTaskRunner() { |
- return new RasterWorkerPoolSequencedTaskRunner(&task_graph_runner_); |
+ return new RasterWorkerPoolSequencedTaskRunner(this); |
} |
RasterWorkerPool::~RasterWorkerPool() {} |
+cc::NamespaceToken RasterWorkerPool::GetNamespaceToken() { |
+ base::AutoLock lock(lock_); |
+ return work_queue_.GetNamespaceToken(); |
+} |
+ |
+void RasterWorkerPool::ScheduleTasks(cc::NamespaceToken token, |
+ cc::TaskGraph* graph) { |
+ TRACE_EVENT2("cc", "RasterWorkerPool::ScheduleTasks", "num_nodes", |
+ graph->nodes.size(), "num_edges", graph->edges.size()); |
+ { |
+ base::AutoLock lock(lock_); |
+ ScheduleTasksWithLockAcquired(token, graph); |
+ } |
+} |
+ |
+void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token, |
+ cc::TaskGraph* graph) { |
+ DCHECK(token.IsValid()); |
+ DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph)); |
+ DCHECK(!shutdown_); |
+ |
+ work_queue_.ScheduleTasks(token, graph); |
+ |
+ // If there is more work available, wake up worker thread. |
+ if (work_queue_.HasReadyToRunTasks()) |
+ has_ready_to_run_tasks_cv_.Signal(); |
+} |
+ |
+void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) { |
+ TRACE_EVENT0("cc", "RasterWorkerPool::WaitForTasksToFinishRunning"); |
+ |
+ DCHECK(token.IsValid()); |
+ |
+ { |
+ base::AutoLock lock(lock_); |
+ base::ThreadRestrictions::ScopedAllowWait allow_wait; |
+ |
+ auto* task_namespace = work_queue_.GetNamespaceForToken(token); |
+ |
+ if (!task_namespace) |
+ return; |
+ |
+ while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace)) |
+ has_namespaces_with_finished_running_tasks_cv_.Wait(); |
+ |
+ // There may be other namespaces that have finished running tasks, so wake |
+ // up another origin thread. |
+ has_namespaces_with_finished_running_tasks_cv_.Signal(); |
+ } |
+} |
+ |
+void RasterWorkerPool::CollectCompletedTasks( |
+ cc::NamespaceToken token, |
+ cc::Task::Vector* completed_tasks) { |
+ TRACE_EVENT0("cc", "RasterWorkerPool::CollectCompletedTasks"); |
+ |
+ { |
+ base::AutoLock lock(lock_); |
+ CollectCompletedTasksWithLockAcquired(token, completed_tasks); |
+ } |
+} |
+ |
+void RasterWorkerPool::CollectCompletedTasksWithLockAcquired( |
+ cc::NamespaceToken token, |
+ cc::Task::Vector* completed_tasks) { |
+ DCHECK(token.IsValid()); |
+ work_queue_.CollectCompletedTasks(token, completed_tasks); |
+} |
+ |
+void RasterWorkerPool::RunTaskWithLockAcquired() { |
+ TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask"); |
+ |
+ lock_.AssertAcquired(); |
+ |
+ auto prioritized_task = work_queue_.GetNextTaskToRun(); |
+ cc::Task* task = prioritized_task.task; |
+ |
+ // There may be more work available, so wake up another worker thread. |
+ has_ready_to_run_tasks_cv_.Signal(); |
+ |
+ // Call WillRun() before releasing |lock_| and running task. |
+ task->WillRun(); |
+ |
+ { |
+ base::AutoUnlock unlock(lock_); |
+ |
+ task->RunOnWorkerThread(); |
+ } |
+ |
+ // This will mark task as finished running. |
+ task->DidRun(); |
+ |
+ work_queue_.CompleteTask(prioritized_task); |
+ |
+ // If namespace has finished running all tasks, wake up origin thread. |
+ if (work_queue_.HasFinishedRunningTasksInNamespace( |
+ prioritized_task.task_namespace)) |
+ has_namespaces_with_finished_running_tasks_cv_.Signal(); |
+} |
+ |
RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure) |
: closure_(closure) {} |
@@ -161,7 +305,7 @@ RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure) |
void RasterWorkerPool::ClosureTask::RunOnWorkerThread() { |
closure_.Run(); |
closure_.Reset(); |
-}; |
+} |
RasterWorkerPool::ClosureTask::~ClosureTask() {} |