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 |