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

Side by Side Diff: content/renderer/raster_worker_pool.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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "content/renderer/raster_worker_pool.h" 5 #include "content/renderer/raster_worker_pool.h"
6 6
7 #include "base/strings/stringprintf.h" 7 #include "base/strings/stringprintf.h"
8 #include "base/threading/thread_restrictions.h"
9 #include "base/trace_event/trace_event.h"
8 10
9 namespace content { 11 namespace content {
10 12
11 // A sequenced task runner which posts tasks to a RasterWorkerPool. 13 // A sequenced task runner which posts tasks to a RasterWorkerPool.
12 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner 14 class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
13 : public base::SequencedTaskRunner { 15 : public base::SequencedTaskRunner {
14 public: 16 public:
15 RasterWorkerPoolSequencedTaskRunner(cc::TaskGraphRunner* task_graph_runner) 17 explicit RasterWorkerPoolSequencedTaskRunner(
18 cc::TaskGraphRunner* task_graph_runner)
16 : task_graph_runner_(task_graph_runner), 19 : task_graph_runner_(task_graph_runner),
17 namespace_token_(task_graph_runner->GetNamespaceToken()) {} 20 namespace_token_(task_graph_runner->GetNamespaceToken()) {}
18 21
19 // Overridden from base::TaskRunner: 22 // Overridden from base::TaskRunner:
20 bool PostDelayedTask(const tracked_objects::Location& from_here, 23 bool PostDelayedTask(const tracked_objects::Location& from_here,
21 const base::Closure& task, 24 const base::Closure& task,
22 base::TimeDelta delay) override { 25 base::TimeDelta delay) override {
23 return PostNonNestableDelayedTask(from_here, task, delay); 26 return PostNonNestableDelayedTask(from_here, task, delay);
24 } 27 }
25 bool RunsTasksOnCurrentThread() const override { return true; } 28 bool RunsTasksOnCurrentThread() const override { return true; }
(...skipping 30 matching lines...) Expand all
56 return true; 59 return true;
57 } 60 }
58 61
59 private: 62 private:
60 ~RasterWorkerPoolSequencedTaskRunner() override { 63 ~RasterWorkerPoolSequencedTaskRunner() override {
61 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_); 64 task_graph_runner_->WaitForTasksToFinishRunning(namespace_token_);
62 task_graph_runner_->CollectCompletedTasks(namespace_token_, 65 task_graph_runner_->CollectCompletedTasks(namespace_token_,
63 &completed_tasks_); 66 &completed_tasks_);
64 }; 67 };
65 68
66 cc::TaskGraphRunner* const task_graph_runner_;
67
68 // Lock to exclusively access all the following members that are used to 69 // Lock to exclusively access all the following members that are used to
69 // implement the SequencedTaskRunner interfaces. 70 // implement the SequencedTaskRunner interfaces.
70 base::Lock lock_; 71 base::Lock lock_;
72
73 cc::TaskGraphRunner* task_graph_runner_;
71 // Namespace used to schedule tasks in the task graph runner. 74 // Namespace used to schedule tasks in the task graph runner.
72 cc::NamespaceToken namespace_token_; 75 cc::NamespaceToken namespace_token_;
73 // List of tasks currently queued up for execution. 76 // List of tasks currently queued up for execution.
74 cc::Task::Vector tasks_; 77 cc::Task::Vector tasks_;
75 // Graph object used for scheduling tasks. 78 // Graph object used for scheduling tasks.
76 cc::TaskGraph graph_; 79 cc::TaskGraph graph_;
77 // Cached vector to avoid allocation when getting the list of complete 80 // Cached vector to avoid allocation when getting the list of complete
78 // tasks. 81 // tasks.
79 cc::Task::Vector completed_tasks_; 82 cc::Task::Vector completed_tasks_;
80 }; 83 };
81 84
82 RasterWorkerPool::RasterWorkerPool() 85 RasterWorkerPool::RasterWorkerPool()
83 : namespace_token_(task_graph_runner_.GetNamespaceToken()) {} 86 : namespace_token_(GetNamespaceToken()),
87 has_ready_to_run_tasks_cv_(&lock_),
88 has_namespaces_with_finished_running_tasks_cv_(&lock_),
89 shutdown_(false) {}
84 90
85 void RasterWorkerPool::Start( 91 void RasterWorkerPool::Start(
86 int num_threads, 92 int num_threads,
87 const base::SimpleThread::Options& thread_options) { 93 const base::SimpleThread::Options& thread_options) {
88 DCHECK(threads_.empty()); 94 DCHECK(threads_.empty());
89 while (threads_.size() < static_cast<size_t>(num_threads)) { 95 while (threads_.size() < static_cast<size_t>(num_threads)) {
90 scoped_ptr<base::DelegateSimpleThread> thread( 96 scoped_ptr<base::DelegateSimpleThread> thread(
91 new base::DelegateSimpleThread( 97 new base::DelegateSimpleThread(
92 this, base::StringPrintf("CompositorTileWorker%u", 98 this, base::StringPrintf("CompositorTileWorker%u",
93 static_cast<unsigned>(threads_.size() + 1)) 99 static_cast<unsigned>(threads_.size() + 1))
94 .c_str(), 100 .c_str(),
95 thread_options)); 101 thread_options));
96 thread->Start(); 102 thread->Start();
97 threads_.push_back(thread.Pass()); 103 threads_.push_back(thread.Pass());
98 } 104 }
99 } 105 }
100 106
101 void RasterWorkerPool::Shutdown() { 107 void RasterWorkerPool::Shutdown() {
102 task_graph_runner_.WaitForTasksToFinishRunning(namespace_token_); 108 WaitForTasksToFinishRunning(namespace_token_);
103 task_graph_runner_.CollectCompletedTasks(namespace_token_, &completed_tasks_); 109 CollectCompletedTasks(namespace_token_, &completed_tasks_);
104 // Shutdown raster threads. 110 // Shutdown raster threads.
105 task_graph_runner_.Shutdown(); 111 {
112 base::AutoLock lock(lock_);
113
114 DCHECK(!work_queue_.HasReadyToRunTasks());
115
116 DCHECK(!shutdown_);
117 shutdown_ = true;
118
119 // Wake up a worker so it knows it should exit. This will cause all workers
120 // to exit as each will wake up another worker before exiting.
121 has_ready_to_run_tasks_cv_.Signal();
122 }
106 while (!threads_.empty()) { 123 while (!threads_.empty()) {
107 threads_.back()->Join(); 124 threads_.back()->Join();
108 threads_.pop_back(); 125 threads_.pop_back();
109 } 126 }
110 } 127 }
111 128
112 // Overridden from base::TaskRunner: 129 // Overridden from base::TaskRunner:
113 bool RasterWorkerPool::PostDelayedTask( 130 bool RasterWorkerPool::PostDelayedTask(
114 const tracked_objects::Location& from_here, 131 const tracked_objects::Location& from_here,
115 const base::Closure& task, 132 const base::Closure& task,
116 base::TimeDelta delay) { 133 base::TimeDelta delay) {
117 base::AutoLock lock(lock_); 134 base::AutoLock lock(lock_);
118 135
119 // Remove completed tasks. 136 // Remove completed tasks.
120 DCHECK(completed_tasks_.empty()); 137 DCHECK(completed_tasks_.empty());
121 task_graph_runner_.CollectCompletedTasks(namespace_token_, &completed_tasks_); 138 CollectCompletedTasksWithLockAcquired(namespace_token_, &completed_tasks_);
122 139
123 cc::Task::Vector::iterator end = std::remove_if( 140 cc::Task::Vector::iterator end = std::remove_if(
124 tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) { 141 tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) {
125 return std::find(this->completed_tasks_.begin(), 142 return std::find(this->completed_tasks_.begin(),
126 this->completed_tasks_.end(), 143 this->completed_tasks_.end(),
127 e) != this->completed_tasks_.end(); 144 e) != this->completed_tasks_.end();
128 }); 145 });
129 tasks_.erase(end, tasks_.end()); 146 tasks_.erase(end, tasks_.end());
130 147
131 tasks_.push_back(make_scoped_refptr(new ClosureTask(task))); 148 tasks_.push_back(make_scoped_refptr(new ClosureTask(task)));
132 graph_.Reset(); 149 graph_.Reset();
133 for (const auto& graph_task : tasks_) 150 for (const auto& graph_task : tasks_)
134 graph_.nodes.push_back(cc::TaskGraph::Node(graph_task.get(), 0, 0)); 151 graph_.nodes.push_back(cc::TaskGraph::Node(graph_task.get(), 0, 0));
135 152
136 task_graph_runner_.ScheduleTasks(namespace_token_, &graph_); 153 ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
137 completed_tasks_.clear(); 154 completed_tasks_.clear();
138 return true; 155 return true;
139 } 156 }
140 157
141 bool RasterWorkerPool::RunsTasksOnCurrentThread() const { 158 bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
142 return true; 159 return true;
143 } 160 }
144 161
145 // Overridden from base::DelegateSimpleThread::Delegate: 162 // Overridden from base::DelegateSimpleThread::Delegate:
146 void RasterWorkerPool::Run() { 163 void RasterWorkerPool::Run() {
147 task_graph_runner_.Run(); 164 base::AutoLock lock(lock_);
165
166 while (true) {
167 if (!work_queue_.HasReadyToRunTasks()) {
168 // Exit when shutdown is set and no more tasks are pending.
169 if (shutdown_)
170 break;
171
172 // Wait for more tasks.
173 has_ready_to_run_tasks_cv_.Wait();
174 continue;
175 }
176
177 RunTaskWithLockAcquired();
178 }
179
180 // We noticed we should exit. Wake up the next worker so it knows it should
181 // exit as well (because the Shutdown() code only signals once).
182 has_ready_to_run_tasks_cv_.Signal();
183 }
184
185 void RasterWorkerPool::FlushForTesting() {
186 base::AutoLock lock(lock_);
187
188 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) {
189 has_namespaces_with_finished_running_tasks_cv_.Wait();
190 }
148 } 191 }
149 192
150 scoped_refptr<base::SequencedTaskRunner> 193 scoped_refptr<base::SequencedTaskRunner>
151 RasterWorkerPool::CreateSequencedTaskRunner() { 194 RasterWorkerPool::CreateSequencedTaskRunner() {
152 return new RasterWorkerPoolSequencedTaskRunner(&task_graph_runner_); 195 return new RasterWorkerPoolSequencedTaskRunner(this);
153 } 196 }
154 197
155 RasterWorkerPool::~RasterWorkerPool() {} 198 RasterWorkerPool::~RasterWorkerPool() {}
156 199
200 void RasterWorkerPool::ScheduleTasks(cc::NamespaceToken token,
201 cc::TaskGraph* graph) {
202 TRACE_EVENT2("cc", "RasterWorkerPool::ScheduleTasks", "num_nodes",
203 graph->nodes.size(), "num_edges", graph->edges.size());
204 {
205 base::AutoLock lock(lock_);
206 ScheduleTasksWithLockAcquired(token, graph);
207 }
208 }
209
210 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
211 cc::TaskGraph* graph) {
212 DCHECK(token.IsValid());
213 DCHECK(!DependencyMismatch(graph));
214 DCHECK(!shutdown_);
215
216 work_queue_.ScheduleTasks(token, graph);
217
218 // If there is more work available, wake up worker thread.
219 if (work_queue_.HasReadyToRunTasks())
220 has_ready_to_run_tasks_cv_.Signal();
221 }
222
223 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
224 TRACE_EVENT0("cc", "RasterWorkerPool::WaitForTasksToFinishRunning");
225
226 DCHECK(token.IsValid());
227
228 {
229 base::AutoLock lock(lock_);
230 base::ThreadRestrictions::ScopedAllowWait allow_wait;
231
232 auto* task_namespace = work_queue_.GetNamespaceForToken(token);
233
234 if (!task_namespace)
235 return;
236
237 while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace))
238 has_namespaces_with_finished_running_tasks_cv_.Wait();
239
240 // There may be other namespaces that have finished running tasks, so wake
241 // up another origin thread.
242 has_namespaces_with_finished_running_tasks_cv_.Signal();
243 }
244 }
245
246 void RasterWorkerPool::CollectCompletedTasks(
247 cc::NamespaceToken token,
248 cc::Task::Vector* completed_tasks) {
249 TRACE_EVENT0("cc", "RasterWorkerPool::CollectCompletedTasks");
250
251 {
252 base::AutoLock lock(lock_);
253 CollectCompletedTasksWithLockAcquired(token, completed_tasks);
254 }
255 }
256
257 void RasterWorkerPool::CollectCompletedTasksWithLockAcquired(
258 cc::NamespaceToken token,
259 cc::Task::Vector* completed_tasks) {
260 DCHECK(token.IsValid());
261 work_queue_.CollectCompletedTasks(token, completed_tasks);
262 }
263
264 void RasterWorkerPool::RunTaskWithLockAcquired() {
265 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
266
267 lock_.AssertAcquired();
268
269 auto prioritized_task = work_queue_.GetNextTaskToRun();
270 cc::Task* task = prioritized_task.task;
271
272 // There may be more work available, so wake up another worker thread.
273 has_ready_to_run_tasks_cv_.Signal();
274
275 // Call WillRun() before releasing |lock_| and running task.
276 task->WillRun();
277
278 {
279 base::AutoUnlock unlock(lock_);
280
281 task->RunOnWorkerThread();
282 }
283
284 // This will mark task as finished running.
285 task->DidRun();
286
287 work_queue_.CompleteTask(prioritized_task);
288
289 // If namespace has finished running all tasks, wake up origin thread.
290 if (work_queue_.HasFinishedRunningTasksInNamespace(
291 prioritized_task.task_namespace))
292 has_namespaces_with_finished_running_tasks_cv_.Signal();
293 }
294
157 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure) 295 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
158 : closure_(closure) {} 296 : closure_(closure) {}
159 297
160 // Overridden from cc::Task: 298 // Overridden from cc::Task:
161 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() { 299 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() {
162 closure_.Run(); 300 closure_.Run();
163 closure_.Reset(); 301 closure_.Reset();
164 }; 302 }
165 303
166 RasterWorkerPool::ClosureTask::~ClosureTask() {} 304 RasterWorkerPool::ClosureTask::~ClosureTask() {}
167 305
168 } // namespace content 306 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698