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

Side by Side Diff: cc/worker_pool.cc

Issue 12217105: cc: Check for completed raster tasks at interval. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 months 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 | Annotate | Revision Log
« cc/tile_manager.cc ('K') | « cc/worker_pool.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/worker_pool.h" 5 #include "cc/worker_pool.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
(...skipping 10 matching lines...) Expand all
21 21
22 class WorkerPoolTaskImpl : public internal::WorkerPoolTask { 22 class WorkerPoolTaskImpl : public internal::WorkerPoolTask {
23 public: 23 public:
24 WorkerPoolTaskImpl(const WorkerPool::Callback& task, 24 WorkerPoolTaskImpl(const WorkerPool::Callback& task,
25 const base::Closure& reply) 25 const base::Closure& reply)
26 : internal::WorkerPoolTask(reply), 26 : internal::WorkerPoolTask(reply),
27 task_(task) {} 27 task_(task) {}
28 28
29 virtual void Run(RenderingStats* rendering_stats) OVERRIDE { 29 virtual void Run(RenderingStats* rendering_stats) OVERRIDE {
30 task_.Run(rendering_stats); 30 task_.Run(rendering_stats);
31 base::subtle::NoBarrier_Store(&completed_, 1);
brianderson 2013/02/12 01:44:31 I think you need a barrier before this store (or a
reveman 2013/02/12 02:29:52 Done.
31 } 32 }
32 33
33 private: 34 private:
34 WorkerPool::Callback task_; 35 WorkerPool::Callback task_;
35 }; 36 };
36 37
37 const char* kWorkerThreadNamePrefix = "Compositor"; 38 const char* kWorkerThreadNamePrefix = "Compositor";
38 39
39 // Allow two pending tasks per worker. This keeps resource usage
40 // low while making sure workers aren't unnecessarily idle.
41 const int kNumPendingTasksPerWorker = 2;
42
43 } // namespace 40 } // namespace
44 41
45 namespace internal { 42 namespace internal {
46 43
47 WorkerPoolTask::WorkerPoolTask(const base::Closure& reply) 44 WorkerPoolTask::WorkerPoolTask(const base::Closure& reply)
48 : reply_(reply) { 45 : reply_(reply) {
46 base::subtle::NoBarrier_Store(&completed_, 0);
brianderson 2013/02/12 01:44:31 I think you need a barrier after this store (or an
reveman 2013/02/12 02:29:52 Done.
49 } 47 }
50 48
51 WorkerPoolTask::~WorkerPoolTask() { 49 WorkerPoolTask::~WorkerPoolTask() {
52 } 50 }
53 51
52 bool WorkerPoolTask::IsPending() {
53 return base::subtle::NoBarrier_Load(&completed_) == 0;
54 }
55
54 void WorkerPoolTask::Completed() { 56 void WorkerPoolTask::Completed() {
57 DCHECK_EQ(base::subtle::NoBarrier_Load(&completed_), 1);
55 reply_.Run(); 58 reply_.Run();
56 } 59 }
57 60
58 } // namespace internal 61 } // namespace internal
59 62
60 WorkerPool::Worker::Worker(WorkerPool* worker_pool, const std::string name) 63 WorkerPool::Worker::Worker(WorkerPool* worker_pool, const std::string name)
61 : base::Thread(name.c_str()), 64 : base::Thread(name.c_str()),
62 worker_pool_(worker_pool), 65 worker_pool_(worker_pool),
63 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
64 rendering_stats_(make_scoped_ptr(new RenderingStats)), 66 rendering_stats_(make_scoped_ptr(new RenderingStats)),
65 record_rendering_stats_(false) { 67 record_rendering_stats_(false) {
66 Start(); 68 Start();
67 DCHECK(IsRunning()); 69 DCHECK(IsRunning());
68 } 70 }
69 71
70 WorkerPool::Worker::~Worker() { 72 WorkerPool::Worker::~Worker() {
71 DCHECK(!IsRunning()); 73 DCHECK(!IsRunning());
72 DCHECK_EQ(pending_tasks_.size(), 0); 74 DCHECK_EQ(pending_tasks_.size(), 0);
73 } 75 }
74 76
75 void WorkerPool::Worker::StopAfterCompletingAllPendingTasks() { 77 void WorkerPool::Worker::StopAfterCompletingAllPendingTasks() {
76 // Signals the thread to exit and returns once all pending tasks have run. 78 // Signals the thread to exit and returns once all pending tasks have run.
77 Stop(); 79 Stop();
78 80
79 // Complete all pending tasks. The Stop() call above guarantees that 81 // Complete all pending tasks. The Stop() call above guarantees that
80 // all tasks have finished running. 82 // all tasks have finished running.
81 while (!pending_tasks_.empty()) 83 while (!pending_tasks_.empty())
82 OnTaskCompleted(); 84 OnTaskCompleted();
83
84 // Cancel all pending replies.
85 weak_ptr_factory_.InvalidateWeakPtrs();
86 } 85 }
87 86
88 void WorkerPool::Worker::PostTask(scoped_ptr<internal::WorkerPoolTask> task) { 87 void WorkerPool::Worker::PostTask(scoped_ptr<internal::WorkerPoolTask> task) {
89 DCHECK_LT(num_pending_tasks(), kNumPendingTasksPerWorker);
90
91 RenderingStats* stats = 88 RenderingStats* stats =
92 record_rendering_stats_ ? rendering_stats_.get() : NULL; 89 record_rendering_stats_ ? rendering_stats_.get() : NULL;
93 90
94 message_loop_proxy()->PostTaskAndReply( 91 message_loop_proxy()->PostTask(
95 FROM_HERE, 92 FROM_HERE,
96 base::Bind(&Worker::RunTask, 93 base::Bind(&Worker::RunTask,
97 base::Unretained(task.get()), 94 base::Unretained(task.get()),
98 base::Unretained(stats)), 95 base::Unretained(stats)));
99 base::Bind(&Worker::OnTaskCompleted, weak_ptr_factory_.GetWeakPtr()));
100 96
101 pending_tasks_.push_back(task.Pass()); 97 pending_tasks_.push_back(task.Pass());
102 98
103 worker_pool_->DidNumPendingTasksChange(); 99 worker_pool_->DidNumPendingTasksChange();
104 } 100 }
105 101
106 void WorkerPool::Worker::Init() { 102 void WorkerPool::Worker::Init() {
107 #if defined(OS_ANDROID) 103 #if defined(OS_ANDROID)
108 // TODO(epenner): Move thread priorities to base. (crbug.com/170549) 104 // TODO(epenner): Move thread priorities to base. (crbug.com/170549)
109 int nice_value = 10; // Idle priority. 105 int nice_value = 10; // Idle priority.
110 setpriority(PRIO_PROCESS, base::PlatformThread::CurrentId(), nice_value); 106 setpriority(PRIO_PROCESS, base::PlatformThread::CurrentId(), nice_value);
111 #endif 107 #endif
112 } 108 }
113 109
114 // static 110 // static
115 void WorkerPool::Worker::RunTask( 111 void WorkerPool::Worker::RunTask(
116 internal::WorkerPoolTask* task, RenderingStats* rendering_stats) { 112 internal::WorkerPoolTask* task, RenderingStats* rendering_stats) {
117 task->Run(rendering_stats); 113 task->Run(rendering_stats);
118 } 114 }
119 115
120 void WorkerPool::Worker::OnTaskCompleted() { 116 void WorkerPool::Worker::OnTaskCompleted() {
121 CHECK(!pending_tasks_.empty()); 117 CHECK(!pending_tasks_.empty());
122 118
123 scoped_ptr<internal::WorkerPoolTask> task = pending_tasks_.take_front(); 119 scoped_ptr<internal::WorkerPoolTask> task = pending_tasks_.take_front();
124 task->Completed(); 120 task->Completed();
125 121
126 worker_pool_->DidNumPendingTasksChange(); 122 worker_pool_->DidNumPendingTasksChange();
127 } 123 }
128 124
125 void WorkerPool::Worker::CheckForCompletedTasks() {
126 while (!pending_tasks_.empty()) {
127 if (pending_tasks_.front()->IsPending())
128 return;
129
130 OnTaskCompleted();
131 }
132 }
133
129 WorkerPool::WorkerPool(size_t num_threads) 134 WorkerPool::WorkerPool(size_t num_threads)
130 : workers_need_sorting_(false), 135 : workers_need_sorting_(false),
131 shutdown_(false) { 136 shutdown_(false) {
132 const std::string thread_name_prefix = kWorkerThreadNamePrefix; 137 const std::string thread_name_prefix = kWorkerThreadNamePrefix;
133 while (workers_.size() < num_threads) { 138 while (workers_.size() < num_threads) {
134 int thread_number = workers_.size() + 1; 139 int thread_number = workers_.size() + 1;
135 workers_.push_back(new Worker( 140 workers_.push_back(new Worker(
136 this, 141 this,
137 thread_name_prefix + StringPrintf("Worker%d", thread_number).c_str())); 142 thread_name_prefix + StringPrintf("Worker%d", thread_number).c_str()));
138 } 143 }
(...skipping 18 matching lines...) Expand all
157 void WorkerPool::PostTaskAndReply( 162 void WorkerPool::PostTaskAndReply(
158 const Callback& task, const base::Closure& reply) { 163 const Callback& task, const base::Closure& reply) {
159 Worker* worker = GetWorkerForNextTask(); 164 Worker* worker = GetWorkerForNextTask();
160 165
161 worker->PostTask( 166 worker->PostTask(
162 make_scoped_ptr(new WorkerPoolTaskImpl( 167 make_scoped_ptr(new WorkerPoolTaskImpl(
163 task, 168 task,
164 reply)).PassAs<internal::WorkerPoolTask>()); 169 reply)).PassAs<internal::WorkerPoolTask>());
165 } 170 }
166 171
167 bool WorkerPool::IsBusy() { 172 void WorkerPool::CheckForCompletedTasks() {
168 Worker* worker = GetWorkerForNextTask(); 173 for (WorkerVector::iterator it = workers_.begin();
169 174 it != workers_.end(); it++) {
170 return worker->num_pending_tasks() >= kNumPendingTasksPerWorker; 175 Worker* worker = *it;
176 worker->CheckForCompletedTasks();
177 }
171 } 178 }
172 179
173 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) { 180 void WorkerPool::SetRecordRenderingStats(bool record_rendering_stats) {
174 for (WorkerVector::iterator it = workers_.begin(); 181 for (WorkerVector::iterator it = workers_.begin();
175 it != workers_.end(); ++it) { 182 it != workers_.end(); ++it) {
176 Worker* worker = *it; 183 Worker* worker = *it;
177 worker->set_record_rendering_stats(record_rendering_stats); 184 worker->set_record_rendering_stats(record_rendering_stats);
178 } 185 }
179 } 186 }
180 187
(...skipping 29 matching lines...) Expand all
210 217
211 void WorkerPool::SortWorkersIfNeeded() { 218 void WorkerPool::SortWorkersIfNeeded() {
212 if (!workers_need_sorting_) 219 if (!workers_need_sorting_)
213 return; 220 return;
214 221
215 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator()); 222 std::sort(workers_.begin(), workers_.end(), NumPendingTasksComparator());
216 workers_need_sorting_ = false; 223 workers_need_sorting_ = false;
217 } 224 }
218 225
219 } // namespace cc 226 } // namespace cc
OLDNEW
« cc/tile_manager.cc ('K') | « cc/worker_pool.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698