| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/scheduler/task_queue_manager.h" | 5 #include "content/renderer/scheduler/task_queue_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/debug/trace_event_argument.h" |
| 9 #include "content/renderer/scheduler/task_queue_selector.h" | 10 #include "content/renderer/scheduler/task_queue_selector.h" |
| 10 | 11 |
| 11 namespace content { | 12 namespace content { |
| 12 namespace internal { | 13 namespace internal { |
| 13 | 14 |
| 14 class TaskQueue : public base::SingleThreadTaskRunner { | 15 class TaskQueue : public base::SingleThreadTaskRunner { |
| 15 public: | 16 public: |
| 16 TaskQueue(TaskQueueManager* task_queue_manager); | 17 TaskQueue(TaskQueueManager* task_queue_manager); |
| 17 | 18 |
| 18 // base::SingleThreadTaskRunner implementation. | 19 // base::SingleThreadTaskRunner implementation. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 34 void SetAutoPump(bool auto_pump); | 35 void SetAutoPump(bool auto_pump); |
| 35 void PumpQueue(); | 36 void PumpQueue(); |
| 36 | 37 |
| 37 bool UpdateWorkQueue(); | 38 bool UpdateWorkQueue(); |
| 38 base::PendingTask TakeTaskFromWorkQueue(); | 39 base::PendingTask TakeTaskFromWorkQueue(); |
| 39 | 40 |
| 40 void WillDeleteTaskQueueManager(); | 41 void WillDeleteTaskQueueManager(); |
| 41 | 42 |
| 42 base::TaskQueue& work_queue() { return work_queue_; } | 43 base::TaskQueue& work_queue() { return work_queue_; } |
| 43 | 44 |
| 45 void set_name(const char* name) { name_ = name; } |
| 46 |
| 47 void AsValueInto(base::debug::TracedValue* state) const; |
| 48 |
| 44 private: | 49 private: |
| 45 ~TaskQueue() override; | 50 ~TaskQueue() override; |
| 46 | 51 |
| 47 void PumpQueueLocked(); | 52 void PumpQueueLocked(); |
| 48 void EnqueueTaskLocked(const base::PendingTask& pending_task); | 53 void EnqueueTaskLocked(const base::PendingTask& pending_task); |
| 54 void TraceWorkQueueSize() const; |
| 49 | 55 |
| 50 // This lock protects all members except the work queue. | 56 // This lock protects all members except the work queue. |
| 51 mutable base::Lock lock_; | 57 mutable base::Lock lock_; |
| 52 TaskQueueManager* task_queue_manager_; | 58 TaskQueueManager* task_queue_manager_; |
| 53 base::TaskQueue incoming_queue_; | 59 base::TaskQueue incoming_queue_; |
| 54 bool auto_pump_; | 60 bool auto_pump_; |
| 61 const char* name_; |
| 55 | 62 |
| 56 base::TaskQueue work_queue_; | 63 base::TaskQueue work_queue_; |
| 57 | 64 |
| 58 DISALLOW_COPY_AND_ASSIGN(TaskQueue); | 65 DISALLOW_COPY_AND_ASSIGN(TaskQueue); |
| 59 }; | 66 }; |
| 60 | 67 |
| 61 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) | 68 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) |
| 62 : task_queue_manager_(task_queue_manager), auto_pump_(true) { | 69 : task_queue_manager_(task_queue_manager), |
| 70 auto_pump_(true), |
| 71 name_(nullptr) { |
| 63 } | 72 } |
| 64 | 73 |
| 65 TaskQueue::~TaskQueue() { | 74 TaskQueue::~TaskQueue() { |
| 66 } | 75 } |
| 67 | 76 |
| 68 void TaskQueue::WillDeleteTaskQueueManager() { | 77 void TaskQueue::WillDeleteTaskQueueManager() { |
| 69 base::AutoLock lock(lock_); | 78 base::AutoLock lock(lock_); |
| 70 task_queue_manager_ = nullptr; | 79 task_queue_manager_ = nullptr; |
| 71 } | 80 } |
| 72 | 81 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 127 |
| 119 bool TaskQueue::UpdateWorkQueue() { | 128 bool TaskQueue::UpdateWorkQueue() { |
| 120 if (!work_queue_.empty()) | 129 if (!work_queue_.empty()) |
| 121 return true; | 130 return true; |
| 122 | 131 |
| 123 { | 132 { |
| 124 base::AutoLock lock(lock_); | 133 base::AutoLock lock(lock_); |
| 125 if (!auto_pump_ || incoming_queue_.empty()) | 134 if (!auto_pump_ || incoming_queue_.empty()) |
| 126 return false; | 135 return false; |
| 127 work_queue_.Swap(&incoming_queue_); | 136 work_queue_.Swap(&incoming_queue_); |
| 137 TraceWorkQueueSize(); |
| 128 return true; | 138 return true; |
| 129 } | 139 } |
| 130 } | 140 } |
| 131 | 141 |
| 132 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() { | 142 base::PendingTask TaskQueue::TakeTaskFromWorkQueue() { |
| 133 base::PendingTask pending_task = work_queue_.front(); | 143 base::PendingTask pending_task = work_queue_.front(); |
| 134 work_queue_.pop(); | 144 work_queue_.pop(); |
| 145 TraceWorkQueueSize(); |
| 135 return pending_task; | 146 return pending_task; |
| 136 } | 147 } |
| 137 | 148 |
| 149 void TaskQueue::TraceWorkQueueSize() const { |
| 150 if (!name_) |
| 151 return; |
| 152 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 153 name_, |
| 154 work_queue_.size()); |
| 155 } |
| 156 |
| 138 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) { | 157 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) { |
| 139 base::AutoLock lock(lock_); | 158 base::AutoLock lock(lock_); |
| 140 EnqueueTaskLocked(pending_task); | 159 EnqueueTaskLocked(pending_task); |
| 141 } | 160 } |
| 142 | 161 |
| 143 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { | 162 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { |
| 144 lock_.AssertAcquired(); | 163 lock_.AssertAcquired(); |
| 145 if (!task_queue_manager_) | 164 if (!task_queue_manager_) |
| 146 return; | 165 return; |
| 147 if (auto_pump_ && incoming_queue_.empty()) | 166 if (auto_pump_ && incoming_queue_.empty()) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 167 } | 186 } |
| 168 if (!work_queue_.empty()) | 187 if (!work_queue_.empty()) |
| 169 task_queue_manager_->PostDoWorkOnMainRunner(); | 188 task_queue_manager_->PostDoWorkOnMainRunner(); |
| 170 } | 189 } |
| 171 | 190 |
| 172 void TaskQueue::PumpQueue() { | 191 void TaskQueue::PumpQueue() { |
| 173 base::AutoLock lock(lock_); | 192 base::AutoLock lock(lock_); |
| 174 PumpQueueLocked(); | 193 PumpQueueLocked(); |
| 175 } | 194 } |
| 176 | 195 |
| 177 } // namespace | 196 void TaskQueue::AsValueInto(base::debug::TracedValue* state) const { |
| 197 base::AutoLock lock(lock_); |
| 198 state->BeginDictionary(); |
| 199 if (name_) |
| 200 state->SetString("name", name_); |
| 201 state->SetBoolean("auto_pump", auto_pump_); |
| 202 state->BeginArray("incoming_queue"); |
| 203 TaskQueueManager::QueueAsValueInto(incoming_queue_, state); |
| 204 state->EndArray(); |
| 205 state->BeginArray("work_queue"); |
| 206 TaskQueueManager::QueueAsValueInto(work_queue_, state); |
| 207 state->EndArray(); |
| 208 state->EndDictionary(); |
| 209 } |
| 210 |
| 211 } // namespace internal |
| 178 | 212 |
| 179 TaskQueueManager::TaskQueueManager( | 213 TaskQueueManager::TaskQueueManager( |
| 180 size_t task_queue_count, | 214 size_t task_queue_count, |
| 181 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 215 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 182 TaskQueueSelector* selector) | 216 TaskQueueSelector* selector) |
| 183 : main_task_runner_(main_task_runner), | 217 : main_task_runner_(main_task_runner), |
| 184 selector_(selector), | 218 selector_(selector), |
| 185 weak_factory_(this) { | 219 weak_factory_(this) { |
| 186 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); | 220 DCHECK(main_task_runner->RunsTasksOnCurrentThread()); |
| 221 TRACE_EVENT_OBJECT_CREATED_WITH_ID( |
| 222 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 223 "TaskQueueManager", |
| 224 this); |
| 187 | 225 |
| 188 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); | 226 task_queue_manager_weak_ptr_ = weak_factory_.GetWeakPtr(); |
| 189 for (size_t i = 0; i < task_queue_count; i++) { | 227 for (size_t i = 0; i < task_queue_count; i++) { |
| 190 scoped_refptr<internal::TaskQueue> queue( | 228 scoped_refptr<internal::TaskQueue> queue( |
| 191 make_scoped_refptr(new internal::TaskQueue(this))); | 229 make_scoped_refptr(new internal::TaskQueue(this))); |
| 192 queues_.push_back(queue); | 230 queues_.push_back(queue); |
| 193 } | 231 } |
| 194 | 232 |
| 195 std::vector<const base::TaskQueue*> work_queues; | 233 std::vector<const base::TaskQueue*> work_queues; |
| 196 for (const auto& queue: queues_) | 234 for (const auto& queue: queues_) |
| 197 work_queues.push_back(&queue->work_queue()); | 235 work_queues.push_back(&queue->work_queue()); |
| 198 selector_->RegisterWorkQueues(work_queues); | 236 selector_->RegisterWorkQueues(work_queues); |
| 199 } | 237 } |
| 200 | 238 |
| 201 TaskQueueManager::~TaskQueueManager() { | 239 TaskQueueManager::~TaskQueueManager() { |
| 240 TRACE_EVENT_OBJECT_DELETED_WITH_ID( |
| 241 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 242 "TaskQueueManager", |
| 243 this); |
| 202 for (auto& queue : queues_) | 244 for (auto& queue : queues_) |
| 203 queue->WillDeleteTaskQueueManager(); | 245 queue->WillDeleteTaskQueueManager(); |
| 204 } | 246 } |
| 205 | 247 |
| 206 internal::TaskQueue* TaskQueueManager::Queue(size_t queue_index) const { | 248 internal::TaskQueue* TaskQueueManager::Queue(size_t queue_index) const { |
| 207 DCHECK_LT(queue_index, queues_.size()); | 249 DCHECK_LT(queue_index, queues_.size()); |
| 208 return queues_[queue_index].get(); | 250 return queues_[queue_index].get(); |
| 209 } | 251 } |
| 210 | 252 |
| 211 scoped_refptr<base::SingleThreadTaskRunner> | 253 scoped_refptr<base::SingleThreadTaskRunner> |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 main_task_runner_->PostTask( | 287 main_task_runner_->PostTask( |
| 246 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_)); | 288 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_)); |
| 247 } | 289 } |
| 248 | 290 |
| 249 void TaskQueueManager::DoWork() { | 291 void TaskQueueManager::DoWork() { |
| 250 main_thread_checker_.CalledOnValidThread(); | 292 main_thread_checker_.CalledOnValidThread(); |
| 251 if (!UpdateWorkQueues()) | 293 if (!UpdateWorkQueues()) |
| 252 return; | 294 return; |
| 253 | 295 |
| 254 size_t queue_index; | 296 size_t queue_index; |
| 255 if (!selector_->SelectWorkQueueToService(&queue_index)) | 297 if (!SelectWorkQueueToService(&queue_index)) |
| 256 return; | 298 return; |
| 257 PostDoWorkOnMainRunner(); | 299 PostDoWorkOnMainRunner(); |
| 258 RunTaskFromWorkQueue(queue_index); | 300 RunTaskFromWorkQueue(queue_index); |
| 259 } | 301 } |
| 260 | 302 |
| 303 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { |
| 304 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); |
| 305 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 306 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), |
| 307 "TaskQueueManager", |
| 308 this, |
| 309 AsValueWithSelectorResult(should_run, *out_queue_index)); |
| 310 return should_run; |
| 311 } |
| 312 |
| 261 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { | 313 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { |
| 262 pending_task->sequence_num = task_sequence_num_.GetNext(); | 314 pending_task->sequence_num = task_sequence_num_.GetNext(); |
| 263 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); | 315 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); |
| 264 } | 316 } |
| 265 | 317 |
| 266 void TaskQueueManager::RunTaskFromWorkQueue(size_t queue_index) { | 318 void TaskQueueManager::RunTaskFromWorkQueue(size_t queue_index) { |
| 267 main_thread_checker_.CalledOnValidThread(); | 319 main_thread_checker_.CalledOnValidThread(); |
| 268 internal::TaskQueue* queue = Queue(queue_index); | 320 internal::TaskQueue* queue = Queue(queue_index); |
| 269 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); | 321 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
| 270 task_annotator_.RunTask( | 322 task_annotator_.RunTask( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 284 } | 336 } |
| 285 | 337 |
| 286 bool TaskQueueManager::PostNonNestableDelayedTask( | 338 bool TaskQueueManager::PostNonNestableDelayedTask( |
| 287 const tracked_objects::Location& from_here, | 339 const tracked_objects::Location& from_here, |
| 288 const base::Closure& task, | 340 const base::Closure& task, |
| 289 base::TimeDelta delay) { | 341 base::TimeDelta delay) { |
| 290 // Defer non-nestable work to the main task runner. | 342 // Defer non-nestable work to the main task runner. |
| 291 return main_task_runner_->PostNonNestableDelayedTask(from_here, task, delay); | 343 return main_task_runner_->PostNonNestableDelayedTask(from_here, task, delay); |
| 292 } | 344 } |
| 293 | 345 |
| 346 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { |
| 347 main_thread_checker_.CalledOnValidThread(); |
| 348 internal::TaskQueue* queue = Queue(queue_index); |
| 349 queue->set_name(name); |
| 350 } |
| 351 |
| 352 scoped_refptr<base::debug::ConvertableToTraceFormat> |
| 353 TaskQueueManager::AsValueWithSelectorResult(bool should_run, |
| 354 size_t selected_queue) const { |
| 355 main_thread_checker_.CalledOnValidThread(); |
| 356 scoped_refptr<base::debug::TracedValue> state = |
| 357 new base::debug::TracedValue(); |
| 358 state->BeginArray("queues"); |
| 359 for (auto& queue : queues_) |
| 360 queue->AsValueInto(state.get()); |
| 361 state->EndArray(); |
| 362 state->BeginDictionary("selector"); |
| 363 selector_->AsValueInto(state.get()); |
| 364 state->EndDictionary(); |
| 365 if (should_run) |
| 366 state->SetInteger("selected_queue", selected_queue); |
| 367 return state; |
| 368 } |
| 369 |
| 370 // static |
| 371 void TaskQueueManager::QueueAsValueInto(const base::TaskQueue& queue, |
| 372 base::debug::TracedValue* state) { |
| 373 base::TaskQueue queue_copy(queue); |
| 374 while (!queue_copy.empty()) { |
| 375 TaskAsValueInto(queue_copy.front(), state); |
| 376 queue_copy.pop(); |
| 377 } |
| 378 } |
| 379 |
| 380 // static |
| 381 void TaskQueueManager::TaskAsValueInto(const base::PendingTask& task, |
| 382 base::debug::TracedValue* state) { |
| 383 state->BeginDictionary(); |
| 384 state->SetString("posted_from", task.posted_from.ToString()); |
| 385 state->SetInteger("sequence_num", task.sequence_num); |
| 386 state->SetBoolean("nestable", task.nestable); |
| 387 state->SetBoolean("is_high_res", task.is_high_res); |
| 388 state->SetDouble( |
| 389 "time_posted", |
| 390 (task.time_posted - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 391 state->SetDouble( |
| 392 "delayed_run_time", |
| 393 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
| 394 state->EndDictionary(); |
| 395 } |
| 396 |
| 294 } // namespace content | 397 } // namespace content |
| OLD | NEW |