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/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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |