| 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 <queue> | 7 #include <queue> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 class TaskQueue : public base::SingleThreadTaskRunner { | 22 class TaskQueue : public base::SingleThreadTaskRunner { |
| 23 public: | 23 public: |
| 24 TaskQueue(TaskQueueManager* task_queue_manager); | 24 TaskQueue(TaskQueueManager* task_queue_manager); |
| 25 | 25 |
| 26 // base::SingleThreadTaskRunner implementation. | 26 // base::SingleThreadTaskRunner implementation. |
| 27 bool RunsTasksOnCurrentThread() const override; | 27 bool RunsTasksOnCurrentThread() const override; |
| 28 bool PostDelayedTask(const tracked_objects::Location& from_here, | 28 bool PostDelayedTask(const tracked_objects::Location& from_here, |
| 29 const base::Closure& task, | 29 const base::Closure& task, |
| 30 base::TimeDelta delay) override { | 30 base::TimeDelta delay) override { |
| 31 return PostDelayedTaskImpl(from_here, task, delay, NORMAL_TASK_TYPE); | 31 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
| 32 } | 32 } |
| 33 | 33 |
| 34 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 34 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
| 35 const base::Closure& task, | 35 const base::Closure& task, |
| 36 base::TimeDelta delay) override { | 36 base::TimeDelta delay) override { |
| 37 return PostDelayedTaskImpl(from_here, task, delay, NON_NESTABLE_TASK_TYPE); | 37 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE); |
| 38 } | 38 } |
| 39 | 39 |
| 40 bool IsQueueEmpty() const; | 40 bool IsQueueEmpty() const; |
| 41 | 41 |
| 42 void SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy); | 42 void SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy); |
| 43 void PumpQueue(); | 43 void PumpQueue(); |
| 44 | 44 |
| 45 bool UpdateWorkQueue(base::TimeTicks* next_pending_delayed_task, | 45 bool UpdateWorkQueue(base::TimeTicks* next_pending_delayed_task, |
| 46 TaskQueueManager::WorkQueueUpdateEventType event_type); | 46 TaskQueueManager::WorkQueueUpdateEventType event_type); |
| 47 base::PendingTask TakeTaskFromWorkQueue(); | 47 base::PendingTask TakeTaskFromWorkQueue(); |
| 48 | 48 |
| 49 void WillDeleteTaskQueueManager(); | 49 void WillDeleteTaskQueueManager(); |
| 50 | 50 |
| 51 base::TaskQueue& work_queue() { return work_queue_; } | 51 base::TaskQueue& work_queue() { return work_queue_; } |
| 52 | 52 |
| 53 void set_name(const char* name) { name_ = name; } | 53 void set_name(const char* name) { name_ = name; } |
| 54 | 54 |
| 55 void AsValueInto(base::trace_event::TracedValue* state) const; | 55 void AsValueInto(base::trace_event::TracedValue* state) const; |
| 56 | 56 |
| 57 private: | 57 private: |
| 58 enum TaskType { | 58 enum class TaskType { |
| 59 NORMAL_TASK_TYPE, | 59 NORMAL, |
| 60 NON_NESTABLE_TASK_TYPE, | 60 NON_NESTABLE, |
| 61 }; | 61 }; |
| 62 | 62 |
| 63 ~TaskQueue() override; | 63 ~TaskQueue() override; |
| 64 | 64 |
| 65 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, | 65 bool PostDelayedTaskImpl(const tracked_objects::Location& from_here, |
| 66 const base::Closure& task, | 66 const base::Closure& task, |
| 67 base::TimeDelta delay, | 67 base::TimeDelta delay, |
| 68 TaskType task_type); | 68 TaskType task_type); |
| 69 | 69 |
| 70 // Adds a task at the end of the incoming task queue and schedules a call to | 70 // Adds a task at the end of the incoming task queue and schedules a call to |
| (...skipping 24 matching lines...) Expand all Loading... |
| 95 std::vector<base::TimeTicks>, | 95 std::vector<base::TimeTicks>, |
| 96 std::greater<base::TimeTicks>> delayed_task_run_times_; | 96 std::greater<base::TimeTicks>> delayed_task_run_times_; |
| 97 | 97 |
| 98 base::TaskQueue work_queue_; | 98 base::TaskQueue work_queue_; |
| 99 | 99 |
| 100 DISALLOW_COPY_AND_ASSIGN(TaskQueue); | 100 DISALLOW_COPY_AND_ASSIGN(TaskQueue); |
| 101 }; | 101 }; |
| 102 | 102 |
| 103 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) | 103 TaskQueue::TaskQueue(TaskQueueManager* task_queue_manager) |
| 104 : task_queue_manager_(task_queue_manager), | 104 : task_queue_manager_(task_queue_manager), |
| 105 pump_policy_(TaskQueueManager::AUTO_PUMP_POLICY), | 105 pump_policy_(TaskQueueManager::PumpPolicy::AUTO), |
| 106 name_(nullptr) { | 106 name_(nullptr) { |
| 107 } | 107 } |
| 108 | 108 |
| 109 TaskQueue::~TaskQueue() { | 109 TaskQueue::~TaskQueue() { |
| 110 } | 110 } |
| 111 | 111 |
| 112 void TaskQueue::WillDeleteTaskQueueManager() { | 112 void TaskQueue::WillDeleteTaskQueueManager() { |
| 113 base::AutoLock lock(lock_); | 113 base::AutoLock lock(lock_); |
| 114 task_queue_manager_ = nullptr; | 114 task_queue_manager_ = nullptr; |
| 115 } | 115 } |
| 116 | 116 |
| 117 bool TaskQueue::RunsTasksOnCurrentThread() const { | 117 bool TaskQueue::RunsTasksOnCurrentThread() const { |
| 118 base::AutoLock lock(lock_); | 118 base::AutoLock lock(lock_); |
| 119 if (!task_queue_manager_) | 119 if (!task_queue_manager_) |
| 120 return false; | 120 return false; |
| 121 return task_queue_manager_->RunsTasksOnCurrentThread(); | 121 return task_queue_manager_->RunsTasksOnCurrentThread(); |
| 122 } | 122 } |
| 123 | 123 |
| 124 bool TaskQueue::PostDelayedTaskImpl(const tracked_objects::Location& from_here, | 124 bool TaskQueue::PostDelayedTaskImpl(const tracked_objects::Location& from_here, |
| 125 const base::Closure& task, | 125 const base::Closure& task, |
| 126 base::TimeDelta delay, | 126 base::TimeDelta delay, |
| 127 TaskType task_type) { | 127 TaskType task_type) { |
| 128 base::AutoLock lock(lock_); | 128 base::AutoLock lock(lock_); |
| 129 if (!task_queue_manager_) | 129 if (!task_queue_manager_) |
| 130 return false; | 130 return false; |
| 131 | 131 |
| 132 base::PendingTask pending_task(from_here, task, base::TimeTicks(), | 132 base::PendingTask pending_task(from_here, task, base::TimeTicks(), |
| 133 task_type != NON_NESTABLE_TASK_TYPE); | 133 task_type != TaskType::NON_NESTABLE); |
| 134 task_queue_manager_->DidQueueTask(&pending_task); | 134 task_queue_manager_->DidQueueTask(&pending_task); |
| 135 | 135 |
| 136 if (delay > base::TimeDelta()) { | 136 if (delay > base::TimeDelta()) { |
| 137 pending_task.delayed_run_time = task_queue_manager_->Now() + delay; | 137 pending_task.delayed_run_time = task_queue_manager_->Now() + delay; |
| 138 delayed_task_run_times_.push(pending_task.delayed_run_time); | 138 delayed_task_run_times_.push(pending_task.delayed_run_time); |
| 139 return task_queue_manager_->PostDelayedTask( | 139 return task_queue_manager_->PostDelayedTask( |
| 140 from_here, Bind(&TaskQueue::EnqueueTask, this, pending_task), delay); | 140 from_here, Bind(&TaskQueue::EnqueueTask, this, pending_task), delay); |
| 141 } | 141 } |
| 142 EnqueueTaskLocked(pending_task); | 142 EnqueueTaskLocked(pending_task); |
| 143 return true; | 143 return true; |
| 144 } | 144 } |
| 145 | 145 |
| 146 bool TaskQueue::IsQueueEmpty() const { | 146 bool TaskQueue::IsQueueEmpty() const { |
| 147 if (!work_queue_.empty()) | 147 if (!work_queue_.empty()) |
| 148 return false; | 148 return false; |
| 149 | 149 |
| 150 { | 150 { |
| 151 base::AutoLock lock(lock_); | 151 base::AutoLock lock(lock_); |
| 152 return incoming_queue_.empty(); | 152 return incoming_queue_.empty(); |
| 153 } | 153 } |
| 154 } | 154 } |
| 155 | 155 |
| 156 bool TaskQueue::ShouldAutoPumpQueueLocked( | 156 bool TaskQueue::ShouldAutoPumpQueueLocked( |
| 157 TaskQueueManager::WorkQueueUpdateEventType event_type) { | 157 TaskQueueManager::WorkQueueUpdateEventType event_type) { |
| 158 lock_.AssertAcquired(); | 158 lock_.AssertAcquired(); |
| 159 if (pump_policy_ == TaskQueueManager::MANUAL_PUMP_POLICY) | 159 if (pump_policy_ == TaskQueueManager::PumpPolicy::MANUAL) |
| 160 return false; | 160 return false; |
| 161 if (pump_policy_ == TaskQueueManager::AUTO_PUMP_AFTER_WAKEUP_POLICY && | 161 if (pump_policy_ == TaskQueueManager::PumpPolicy::AFTER_WAKEUP && |
| 162 event_type != TaskQueueManager::AFTER_WAKEUP_EVENT_TYPE) | 162 event_type != TaskQueueManager::WorkQueueUpdateEventType::AFTER_WAKEUP) |
| 163 return false; | 163 return false; |
| 164 if (incoming_queue_.empty()) | 164 if (incoming_queue_.empty()) |
| 165 return false; | 165 return false; |
| 166 return true; | 166 return true; |
| 167 } | 167 } |
| 168 | 168 |
| 169 bool TaskQueue::UpdateWorkQueue( | 169 bool TaskQueue::UpdateWorkQueue( |
| 170 base::TimeTicks* next_pending_delayed_task, | 170 base::TimeTicks* next_pending_delayed_task, |
| 171 TaskQueueManager::WorkQueueUpdateEventType event_type) { | 171 TaskQueueManager::WorkQueueUpdateEventType event_type) { |
| 172 if (!work_queue_.empty()) | 172 if (!work_queue_.empty()) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 202 | 202 |
| 203 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) { | 203 void TaskQueue::EnqueueTask(const base::PendingTask& pending_task) { |
| 204 base::AutoLock lock(lock_); | 204 base::AutoLock lock(lock_); |
| 205 EnqueueTaskLocked(pending_task); | 205 EnqueueTaskLocked(pending_task); |
| 206 } | 206 } |
| 207 | 207 |
| 208 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { | 208 void TaskQueue::EnqueueTaskLocked(const base::PendingTask& pending_task) { |
| 209 lock_.AssertAcquired(); | 209 lock_.AssertAcquired(); |
| 210 if (!task_queue_manager_) | 210 if (!task_queue_manager_) |
| 211 return; | 211 return; |
| 212 if (pump_policy_ == TaskQueueManager::AUTO_PUMP_POLICY && | 212 if (pump_policy_ == TaskQueueManager::PumpPolicy::AUTO && |
| 213 incoming_queue_.empty()) | 213 incoming_queue_.empty()) |
| 214 task_queue_manager_->MaybePostDoWorkOnMainRunner(); | 214 task_queue_manager_->MaybePostDoWorkOnMainRunner(); |
| 215 incoming_queue_.push(pending_task); | 215 incoming_queue_.push(pending_task); |
| 216 | 216 |
| 217 if (!pending_task.delayed_run_time.is_null()) { | 217 if (!pending_task.delayed_run_time.is_null()) { |
| 218 // Update the time of the next pending delayed task. | 218 // Update the time of the next pending delayed task. |
| 219 while (!delayed_task_run_times_.empty() && | 219 while (!delayed_task_run_times_.empty() && |
| 220 delayed_task_run_times_.top() <= pending_task.delayed_run_time) { | 220 delayed_task_run_times_.top() <= pending_task.delayed_run_time) { |
| 221 delayed_task_run_times_.pop(); | 221 delayed_task_run_times_.pop(); |
| 222 } | 222 } |
| 223 // Clear the delayed run time because we've already applied the delay | 223 // Clear the delayed run time because we've already applied the delay |
| 224 // before getting here. | 224 // before getting here. |
| 225 incoming_queue_.back().delayed_run_time = base::TimeTicks(); | 225 incoming_queue_.back().delayed_run_time = base::TimeTicks(); |
| 226 } | 226 } |
| 227 } | 227 } |
| 228 | 228 |
| 229 void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) { | 229 void TaskQueue::SetPumpPolicy(TaskQueueManager::PumpPolicy pump_policy) { |
| 230 base::AutoLock lock(lock_); | 230 base::AutoLock lock(lock_); |
| 231 if (pump_policy == TaskQueueManager::AUTO_PUMP_POLICY && | 231 if (pump_policy == TaskQueueManager::PumpPolicy::AUTO && |
| 232 pump_policy_ != TaskQueueManager::AUTO_PUMP_POLICY) { | 232 pump_policy_ != TaskQueueManager::PumpPolicy::AUTO) { |
| 233 PumpQueueLocked(); | 233 PumpQueueLocked(); |
| 234 } | 234 } |
| 235 pump_policy_ = pump_policy; | 235 pump_policy_ = pump_policy; |
| 236 } | 236 } |
| 237 | 237 |
| 238 void TaskQueue::PumpQueueLocked() { | 238 void TaskQueue::PumpQueueLocked() { |
| 239 lock_.AssertAcquired(); | 239 lock_.AssertAcquired(); |
| 240 while (!incoming_queue_.empty()) { | 240 while (!incoming_queue_.empty()) { |
| 241 work_queue_.push(incoming_queue_.front()); | 241 work_queue_.push(incoming_queue_.front()); |
| 242 incoming_queue_.pop(); | 242 incoming_queue_.pop(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 262 state->BeginArray("work_queue"); | 262 state->BeginArray("work_queue"); |
| 263 QueueAsValueInto(work_queue_, state); | 263 QueueAsValueInto(work_queue_, state); |
| 264 state->EndArray(); | 264 state->EndArray(); |
| 265 state->EndDictionary(); | 265 state->EndDictionary(); |
| 266 } | 266 } |
| 267 | 267 |
| 268 // static | 268 // static |
| 269 const char* TaskQueue::PumpPolicyToString( | 269 const char* TaskQueue::PumpPolicyToString( |
| 270 TaskQueueManager::PumpPolicy pump_policy) { | 270 TaskQueueManager::PumpPolicy pump_policy) { |
| 271 switch (pump_policy) { | 271 switch (pump_policy) { |
| 272 case TaskQueueManager::AUTO_PUMP_POLICY: | 272 case TaskQueueManager::PumpPolicy::AUTO: |
| 273 return "auto_pump"; | 273 return "auto"; |
| 274 case TaskQueueManager::AUTO_PUMP_AFTER_WAKEUP_POLICY: | 274 case TaskQueueManager::PumpPolicy::AFTER_WAKEUP: |
| 275 return "auto_pump_after_wakeup"; | 275 return "after_wakeup"; |
| 276 case TaskQueueManager::MANUAL_PUMP_POLICY: | 276 case TaskQueueManager::PumpPolicy::MANUAL: |
| 277 return "manual_pump"; | 277 return "manual"; |
| 278 default: | 278 default: |
| 279 NOTREACHED(); | 279 NOTREACHED(); |
| 280 return nullptr; | 280 return nullptr; |
| 281 } | 281 } |
| 282 } | 282 } |
| 283 | 283 |
| 284 // static | 284 // static |
| 285 void TaskQueue::QueueAsValueInto(const base::TaskQueue& queue, | 285 void TaskQueue::QueueAsValueInto(const base::TaskQueue& queue, |
| 286 base::trace_event::TracedValue* state) { | 286 base::trace_event::TracedValue* state) { |
| 287 base::TaskQueue queue_copy(queue); | 287 base::TaskQueue queue_copy(queue); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 void TaskQueueManager::DoWork(bool posted_from_main_thread) { | 409 void TaskQueueManager::DoWork(bool posted_from_main_thread) { |
| 410 if (posted_from_main_thread) { | 410 if (posted_from_main_thread) { |
| 411 pending_dowork_count_--; | 411 pending_dowork_count_--; |
| 412 DCHECK_GE(pending_dowork_count_, 0); | 412 DCHECK_GE(pending_dowork_count_, 0); |
| 413 } | 413 } |
| 414 DCHECK(main_thread_checker_.CalledOnValidThread()); | 414 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 415 | 415 |
| 416 base::TimeTicks next_pending_delayed_task( | 416 base::TimeTicks next_pending_delayed_task( |
| 417 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); | 417 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); |
| 418 | 418 |
| 419 if (!UpdateWorkQueues(&next_pending_delayed_task, BEFORE_WAKEUP_EVENT_TYPE)) | 419 if (!UpdateWorkQueues(&next_pending_delayed_task, |
| 420 WorkQueueUpdateEventType::BEFORE_WAKEUP)) |
| 420 return; | 421 return; |
| 421 | 422 |
| 422 base::PendingTask previous_task((tracked_objects::Location()), | 423 base::PendingTask previous_task((tracked_objects::Location()), |
| 423 (base::Closure())); | 424 (base::Closure())); |
| 424 for (int i = 0; i < work_batch_size_; i++) { | 425 for (int i = 0; i < work_batch_size_; i++) { |
| 425 // Interrupt the work batch if we should run the next delayed task. | 426 // Interrupt the work batch if we should run the next delayed task. |
| 426 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && | 427 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && |
| 427 Now() >= next_pending_delayed_task) | 428 Now() >= next_pending_delayed_task) |
| 428 return; | 429 return; |
| 429 | 430 |
| 430 size_t queue_index; | 431 size_t queue_index; |
| 431 if (!SelectWorkQueueToService(&queue_index)) | 432 if (!SelectWorkQueueToService(&queue_index)) |
| 432 return; | 433 return; |
| 433 // Note that this function won't post another call to DoWork if one is | 434 // Note that this function won't post another call to DoWork if one is |
| 434 // already pending, so it is safe to call it in a loop. | 435 // already pending, so it is safe to call it in a loop. |
| 435 MaybePostDoWorkOnMainRunner(); | 436 MaybePostDoWorkOnMainRunner(); |
| 436 ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task); | 437 ProcessTaskFromWorkQueue(queue_index, i > 0, &previous_task); |
| 437 | 438 |
| 438 if (!UpdateWorkQueues(&next_pending_delayed_task, AFTER_WAKEUP_EVENT_TYPE)) | 439 if (!UpdateWorkQueues(&next_pending_delayed_task, |
| 440 WorkQueueUpdateEventType::AFTER_WAKEUP)) |
| 439 return; | 441 return; |
| 440 } | 442 } |
| 441 } | 443 } |
| 442 | 444 |
| 443 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { | 445 bool TaskQueueManager::SelectWorkQueueToService(size_t* out_queue_index) { |
| 444 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); | 446 bool should_run = selector_->SelectWorkQueueToService(out_queue_index); |
| 445 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 447 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
| 446 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this, | 448 TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "TaskQueueManager", this, |
| 447 AsValueWithSelectorResult(should_run, *out_queue_index)); | 449 AsValueWithSelectorResult(should_run, *out_queue_index)); |
| 448 return should_run; | 450 return should_run; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 state->EndArray(); | 544 state->EndArray(); |
| 543 state->BeginDictionary("selector"); | 545 state->BeginDictionary("selector"); |
| 544 selector_->AsValueInto(state.get()); | 546 selector_->AsValueInto(state.get()); |
| 545 state->EndDictionary(); | 547 state->EndDictionary(); |
| 546 if (should_run) | 548 if (should_run) |
| 547 state->SetInteger("selected_queue", selected_queue); | 549 state->SetInteger("selected_queue", selected_queue); |
| 548 return state; | 550 return state; |
| 549 } | 551 } |
| 550 | 552 |
| 551 } // namespace content | 553 } // namespace content |
| OLD | NEW |