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

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: feedback Created 5 years 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
« no previous file with comments | « content/renderer/raster_worker_pool.h ('k') | content/renderer/raster_worker_pool_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 DCHECK(!work_queue_.HasAnyNamespaces());
116
117 DCHECK(!shutdown_);
118 shutdown_ = true;
119
120 // Wake up a worker so it knows it should exit. This will cause all workers
121 // to exit as each will wake up another worker before exiting.
122 has_ready_to_run_tasks_cv_.Signal();
123 }
106 while (!threads_.empty()) { 124 while (!threads_.empty()) {
107 threads_.back()->Join(); 125 threads_.back()->Join();
108 threads_.pop_back(); 126 threads_.pop_back();
109 } 127 }
110 } 128 }
111 129
112 // Overridden from base::TaskRunner: 130 // Overridden from base::TaskRunner:
113 bool RasterWorkerPool::PostDelayedTask( 131 bool RasterWorkerPool::PostDelayedTask(
114 const tracked_objects::Location& from_here, 132 const tracked_objects::Location& from_here,
115 const base::Closure& task, 133 const base::Closure& task,
116 base::TimeDelta delay) { 134 base::TimeDelta delay) {
117 base::AutoLock lock(lock_); 135 base::AutoLock lock(lock_);
118 136
119 // Remove completed tasks. 137 // Remove completed tasks.
120 DCHECK(completed_tasks_.empty()); 138 DCHECK(completed_tasks_.empty());
121 task_graph_runner_.CollectCompletedTasks(namespace_token_, &completed_tasks_); 139 CollectCompletedTasksWithLockAcquired(namespace_token_, &completed_tasks_);
122 140
123 cc::Task::Vector::iterator end = std::remove_if( 141 cc::Task::Vector::iterator end = std::remove_if(
124 tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) { 142 tasks_.begin(), tasks_.end(), [this](const scoped_refptr<cc::Task>& e) {
125 return std::find(this->completed_tasks_.begin(), 143 return std::find(this->completed_tasks_.begin(),
126 this->completed_tasks_.end(), 144 this->completed_tasks_.end(),
127 e) != this->completed_tasks_.end(); 145 e) != this->completed_tasks_.end();
128 }); 146 });
129 tasks_.erase(end, tasks_.end()); 147 tasks_.erase(end, tasks_.end());
130 148
131 tasks_.push_back(make_scoped_refptr(new ClosureTask(task))); 149 tasks_.push_back(make_scoped_refptr(new ClosureTask(task)));
132 graph_.Reset(); 150 graph_.Reset();
133 for (const auto& graph_task : tasks_) 151 for (const auto& graph_task : tasks_)
134 graph_.nodes.push_back(cc::TaskGraph::Node(graph_task.get(), 0, 0)); 152 graph_.nodes.push_back(cc::TaskGraph::Node(graph_task.get(), 0, 0));
135 153
136 task_graph_runner_.ScheduleTasks(namespace_token_, &graph_); 154 ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
137 completed_tasks_.clear(); 155 completed_tasks_.clear();
138 return true; 156 return true;
139 } 157 }
140 158
141 bool RasterWorkerPool::RunsTasksOnCurrentThread() const { 159 bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
142 return true; 160 return true;
143 } 161 }
144 162
145 // Overridden from base::DelegateSimpleThread::Delegate: 163 // Overridden from base::DelegateSimpleThread::Delegate:
146 void RasterWorkerPool::Run() { 164 void RasterWorkerPool::Run() {
147 task_graph_runner_.Run(); 165 base::AutoLock lock(lock_);
166
167 while (true) {
168 if (!work_queue_.HasReadyToRunTasks()) {
169 // Exit when shutdown is set and no more tasks are pending.
170 if (shutdown_)
171 break;
172
173 // Wait for more tasks.
174 has_ready_to_run_tasks_cv_.Wait();
175 continue;
176 }
177
178 RunTaskWithLockAcquired();
179 }
180
181 // We noticed we should exit. Wake up the next worker so it knows it should
182 // exit as well (because the Shutdown() code only signals once).
183 has_ready_to_run_tasks_cv_.Signal();
184 }
185
186 void RasterWorkerPool::FlushForTesting() {
187 base::AutoLock lock(lock_);
188
189 while (!work_queue_.HasFinishedRunningTasksInAllNamespaces()) {
190 has_namespaces_with_finished_running_tasks_cv_.Wait();
191 }
148 } 192 }
149 193
150 scoped_refptr<base::SequencedTaskRunner> 194 scoped_refptr<base::SequencedTaskRunner>
151 RasterWorkerPool::CreateSequencedTaskRunner() { 195 RasterWorkerPool::CreateSequencedTaskRunner() {
152 return new RasterWorkerPoolSequencedTaskRunner(&task_graph_runner_); 196 return new RasterWorkerPoolSequencedTaskRunner(this);
153 } 197 }
154 198
155 RasterWorkerPool::~RasterWorkerPool() {} 199 RasterWorkerPool::~RasterWorkerPool() {}
156 200
201 cc::NamespaceToken RasterWorkerPool::GetNamespaceToken() {
202 base::AutoLock lock(lock_);
203 return work_queue_.GetNamespaceToken();
204 }
205
206 void RasterWorkerPool::ScheduleTasks(cc::NamespaceToken token,
207 cc::TaskGraph* graph) {
208 TRACE_EVENT2("cc", "RasterWorkerPool::ScheduleTasks", "num_nodes",
209 graph->nodes.size(), "num_edges", graph->edges.size());
210 {
211 base::AutoLock lock(lock_);
212 ScheduleTasksWithLockAcquired(token, graph);
213 }
214 }
215
216 void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
217 cc::TaskGraph* graph) {
218 DCHECK(token.IsValid());
219 DCHECK(!cc::TaskGraphWorkQueue::DependencyMismatch(graph));
220 DCHECK(!shutdown_);
221
222 work_queue_.ScheduleTasks(token, graph);
223
224 // If there is more work available, wake up worker thread.
225 if (work_queue_.HasReadyToRunTasks())
226 has_ready_to_run_tasks_cv_.Signal();
227 }
228
229 void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
230 TRACE_EVENT0("cc", "RasterWorkerPool::WaitForTasksToFinishRunning");
231
232 DCHECK(token.IsValid());
233
234 {
235 base::AutoLock lock(lock_);
236 base::ThreadRestrictions::ScopedAllowWait allow_wait;
237
238 auto* task_namespace = work_queue_.GetNamespaceForToken(token);
239
240 if (!task_namespace)
241 return;
242
243 while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace))
244 has_namespaces_with_finished_running_tasks_cv_.Wait();
245
246 // There may be other namespaces that have finished running tasks, so wake
247 // up another origin thread.
248 has_namespaces_with_finished_running_tasks_cv_.Signal();
249 }
250 }
251
252 void RasterWorkerPool::CollectCompletedTasks(
253 cc::NamespaceToken token,
254 cc::Task::Vector* completed_tasks) {
255 TRACE_EVENT0("cc", "RasterWorkerPool::CollectCompletedTasks");
256
257 {
258 base::AutoLock lock(lock_);
259 CollectCompletedTasksWithLockAcquired(token, completed_tasks);
260 }
261 }
262
263 void RasterWorkerPool::CollectCompletedTasksWithLockAcquired(
264 cc::NamespaceToken token,
265 cc::Task::Vector* completed_tasks) {
266 DCHECK(token.IsValid());
267 work_queue_.CollectCompletedTasks(token, completed_tasks);
268 }
269
270 void RasterWorkerPool::RunTaskWithLockAcquired() {
271 TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
272
273 lock_.AssertAcquired();
274
275 auto prioritized_task = work_queue_.GetNextTaskToRun();
276 cc::Task* task = prioritized_task.task;
277
278 // There may be more work available, so wake up another worker thread.
279 has_ready_to_run_tasks_cv_.Signal();
280
281 // Call WillRun() before releasing |lock_| and running task.
282 task->WillRun();
283
284 {
285 base::AutoUnlock unlock(lock_);
286
287 task->RunOnWorkerThread();
288 }
289
290 // This will mark task as finished running.
291 task->DidRun();
292
293 work_queue_.CompleteTask(prioritized_task);
294
295 // If namespace has finished running all tasks, wake up origin thread.
296 if (work_queue_.HasFinishedRunningTasksInNamespace(
297 prioritized_task.task_namespace))
298 has_namespaces_with_finished_running_tasks_cv_.Signal();
299 }
300
157 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure) 301 RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
158 : closure_(closure) {} 302 : closure_(closure) {}
159 303
160 // Overridden from cc::Task: 304 // Overridden from cc::Task:
161 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() { 305 void RasterWorkerPool::ClosureTask::RunOnWorkerThread() {
162 closure_.Run(); 306 closure_.Run();
163 closure_.Reset(); 307 closure_.Reset();
164 }; 308 }
165 309
166 RasterWorkerPool::ClosureTask::~ClosureTask() {} 310 RasterWorkerPool::ClosureTask::~ClosureTask() {}
167 311
168 } // namespace content 312 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/raster_worker_pool.h ('k') | content/renderer/raster_worker_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698