OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "platform/scheduler/base/task_queue_impl.h" | 5 #include "platform/scheduler/base/task_queue_impl.h" |
6 | 6 |
7 #include "base/trace_event/blame_context.h" | 7 #include "base/trace_event/blame_context.h" |
8 #include "platform/scheduler/base/task_queue_manager.h" | 8 #include "platform/scheduler/base/task_queue_manager.h" |
9 #include "platform/scheduler/base/task_queue_manager_delegate.h" | 9 #include "platform/scheduler/base/task_queue_manager_delegate.h" |
10 #include "platform/scheduler/base/time_domain.h" | 10 #include "platform/scheduler/base/time_domain.h" |
11 #include "platform/scheduler/base/work_queue.h" | 11 #include "platform/scheduler/base/work_queue.h" |
12 | 12 |
13 namespace blink { | 13 namespace blink { |
14 namespace scheduler { | 14 namespace scheduler { |
15 | |
16 TaskQueue::TaskHandle::TaskHandle() : enqueue_order_(0), sequence_number_(0) {} | |
17 | |
18 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, uint64_t enqueue_order) | |
19 : enqueue_order_(enqueue_order), | |
20 #if DCHECK_IS_ON() | |
21 task_queue_(task_queue), | |
22 #endif | |
23 sequence_number_(0) { | |
24 DCHECK_GT(enqueue_order, 0ull); | |
25 } | |
26 | |
27 TaskQueue::TaskHandle::TaskHandle(TaskQueue* task_queue, | |
28 base::TimeTicks scheduled_run_time, | |
29 int sequence_number) | |
30 : enqueue_order_(0), | |
31 scheduled_run_time_(scheduled_run_time), | |
32 #if DCHECK_IS_ON() | |
33 task_queue_(task_queue), | |
34 #endif | |
35 sequence_number_(sequence_number) { | |
36 DCHECK(!scheduled_run_time.is_null()); | |
37 } | |
38 | |
39 TaskQueue::TaskHandle::operator bool() const { | |
40 return !scheduled_run_time_.is_null() || | |
41 internal::EnqueueOrderGenerator::isValidEnqueueOrder(enqueue_order_); | |
42 } | |
43 | |
15 namespace internal { | 44 namespace internal { |
16 | 45 |
17 TaskQueueImpl::TaskQueueImpl( | 46 TaskQueueImpl::TaskQueueImpl( |
18 TaskQueueManager* task_queue_manager, | 47 TaskQueueManager* task_queue_manager, |
19 TimeDomain* time_domain, | 48 TimeDomain* time_domain, |
20 const Spec& spec, | 49 const Spec& spec, |
21 const char* disabled_by_default_tracing_category, | 50 const char* disabled_by_default_tracing_category, |
22 const char* disabled_by_default_verbose_tracing_category) | 51 const char* disabled_by_default_verbose_tracing_category) |
23 : thread_id_(base::PlatformThread::CurrentId()), | 52 : thread_id_(base::PlatformThread::CurrentId()), |
24 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 53 any_thread_(task_queue_manager, spec.pump_policy, time_domain), |
(...skipping 59 matching lines...) Loading... | |
84 bool nestable, | 113 bool nestable, |
85 EnqueueOrder enqueue_order) | 114 EnqueueOrder enqueue_order) |
86 : PendingTask(posted_from, task, desired_run_time, nestable), | 115 : PendingTask(posted_from, task, desired_run_time, nestable), |
87 #ifndef NDEBUG | 116 #ifndef NDEBUG |
88 enqueue_order_set_(true), | 117 enqueue_order_set_(true), |
89 #endif | 118 #endif |
90 enqueue_order_(enqueue_order) { | 119 enqueue_order_(enqueue_order) { |
91 sequence_num = sequence_number; | 120 sequence_num = sequence_number; |
92 } | 121 } |
93 | 122 |
123 bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()( | |
124 const Task& a, | |
125 const Task& b) const { | |
126 if (a.delayed_run_time < b.delayed_run_time) | |
127 return true; | |
128 | |
129 if (a.delayed_run_time > b.delayed_run_time) | |
130 return false; | |
131 | |
132 // If the times happen to match, then we use the sequence number to decide. | |
133 // Compare the difference to support integer roll-over. | |
134 return (a.sequence_num - b.sequence_num) < 0; | |
135 } | |
136 | |
137 // static | |
138 bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a, | |
139 const Task& b) { | |
140 return a.enqueue_order() < b.enqueue_order(); | |
141 } | |
142 | |
143 // static | |
144 bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a, | |
145 const Task& b) { | |
146 if (a.delayed_run_time < b.delayed_run_time) | |
147 return true; | |
148 | |
149 if (a.delayed_run_time > b.delayed_run_time) | |
150 return false; | |
151 | |
152 // If the times happen to match, then we use the sequence number to decide. | |
153 // Compare the difference to support integer roll-over. | |
154 return (a.sequence_num - b.sequence_num) < 0; | |
155 } | |
156 | |
94 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 157 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
95 PumpPolicy pump_policy, | 158 PumpPolicy pump_policy, |
96 TimeDomain* time_domain) | 159 TimeDomain* time_domain) |
97 : task_queue_manager(task_queue_manager), | 160 : task_queue_manager(task_queue_manager), |
98 pump_policy(pump_policy), | 161 pump_policy(pump_policy), |
99 time_domain(time_domain) {} | 162 time_domain(time_domain), |
163 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { | |
164 } | |
100 | 165 |
101 TaskQueueImpl::AnyThread::~AnyThread() {} | 166 TaskQueueImpl::AnyThread::~AnyThread() {} |
102 | 167 |
103 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 168 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
104 TaskQueueManager* task_queue_manager, | 169 TaskQueueManager* task_queue_manager, |
105 PumpPolicy pump_policy, | 170 PumpPolicy pump_policy, |
106 TaskQueueImpl* task_queue, | 171 TaskQueueImpl* task_queue, |
107 TimeDomain* time_domain) | 172 TimeDomain* time_domain) |
108 : task_queue_manager(task_queue_manager), | 173 : task_queue_manager(task_queue_manager), |
109 pump_policy(pump_policy), | 174 pump_policy(pump_policy), |
110 time_domain(time_domain), | 175 time_domain(time_domain), |
111 delayed_work_queue(new WorkQueue(task_queue, "delayed")), | 176 delayed_work_queue( |
112 immediate_work_queue(new WorkQueue(task_queue, "immediate")), | 177 new WorkQueue(task_queue, |
178 "delayed", | |
179 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), | |
180 immediate_work_queue( | |
181 new WorkQueue(task_queue, | |
182 "immediate", | |
183 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), | |
113 set_index(0), | 184 set_index(0), |
114 is_enabled(true), | 185 is_enabled(true), |
115 blame_context(nullptr) {} | 186 blame_context(nullptr) {} |
116 | 187 |
117 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 188 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
118 | 189 |
119 void TaskQueueImpl::UnregisterTaskQueue() { | 190 void TaskQueueImpl::UnregisterTaskQueue() { |
120 base::AutoLock lock(any_thread_lock_); | 191 base::AutoLock lock(any_thread_lock_); |
121 if (main_thread_only().time_domain) | 192 if (main_thread_only().time_domain) |
122 main_thread_only().time_domain->UnregisterQueue(this); | 193 main_thread_only().time_domain->UnregisterQueue(this); |
123 if (!any_thread().task_queue_manager) | 194 if (!any_thread().task_queue_manager) |
124 return; | 195 return; |
125 any_thread().time_domain = nullptr; | 196 any_thread().time_domain = nullptr; |
126 main_thread_only().time_domain = nullptr; | 197 main_thread_only().time_domain = nullptr; |
127 any_thread().task_queue_manager->UnregisterTaskQueue(this); | 198 any_thread().task_queue_manager->UnregisterTaskQueue(this); |
128 | 199 |
129 any_thread().task_queue_manager = nullptr; | 200 any_thread().task_queue_manager = nullptr; |
130 main_thread_only().task_queue_manager = nullptr; | 201 main_thread_only().task_queue_manager = nullptr; |
131 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); | 202 main_thread_only().delayed_incoming_queue.clear(); |
132 any_thread().immediate_incoming_queue = std::queue<Task>(); | 203 any_thread().immediate_incoming_queue.clear(); |
133 main_thread_only().immediate_work_queue.reset(); | 204 main_thread_only().immediate_work_queue.reset(); |
134 main_thread_only().delayed_work_queue.reset(); | 205 main_thread_only().delayed_work_queue.reset(); |
135 } | 206 } |
136 | 207 |
137 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { | 208 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { |
138 base::AutoLock lock(any_thread_lock_); | 209 base::AutoLock lock(any_thread_lock_); |
139 return base::PlatformThread::CurrentId() == thread_id_; | 210 return base::PlatformThread::CurrentId() == thread_id_; |
140 } | 211 } |
141 | 212 |
213 TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask( | |
214 const tracked_objects::Location& from_here, | |
215 const base::Closure& task, | |
216 base::TimeDelta delay) { | |
217 if (!main_thread_only().task_queue_manager) | |
218 return TaskHandle(); | |
219 | |
220 EnqueueOrder sequence_number = | |
221 main_thread_only().task_queue_manager->GetNextSequenceNumber(); | |
222 | |
223 if (delay.is_zero()) { | |
224 base::AutoLock lock(any_thread_lock_); | |
225 PushOntoImmediateIncomingQueueLocked( | |
226 Task(from_here, task, base::TimeTicks(), sequence_number, true, | |
227 sequence_number)); | |
228 | |
229 return TaskHandle(this, sequence_number); | |
230 } else { | |
231 DCHECK_GT(delay, base::TimeDelta()); | |
232 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | |
233 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | |
234 PushOntoDelayedIncomingQueueFromMainThread( | |
235 Task(from_here, task, time_domain_delayed_run_time, sequence_number, | |
236 true), | |
237 time_domain_now); | |
238 | |
239 return TaskHandle(this, time_domain_delayed_run_time, sequence_number); | |
240 } | |
241 } | |
242 | |
243 bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) { | |
244 if (!handle) | |
245 return false; | |
246 | |
247 // If the TaskQueueManager has gone away, pretend we have canceled the task | |
248 // because this simplifies logic in TimerBase::stop. | |
249 if (!main_thread_only().task_queue_manager) | |
Sami
2016/08/18 15:53:43
We don't seem to need TQM below anymore, so maybe
alex clarke (OOO till 29th)
2016/08/18 16:51:41
Right but we do need the immediate_work_queue & de
| |
250 return true; | |
251 | |
252 #if DCHECK_IS_ON() | |
253 DCHECK_EQ(handle.task_queue_, this); | |
254 #endif | |
255 | |
256 if (handle.scheduled_run_time_.is_null()) { | |
257 // It's an immediate task. | |
258 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
Sami
2016/08/18 15:53:43
nit: not sure if the compiler is smart enough to e
alex clarke (OOO till 29th)
2016/08/18 16:51:41
Done.
| |
259 handle.sequence_number_, false, handle.enqueue_order_); | |
260 if (main_thread_only().immediate_work_queue->CancelTask(fake_task)) | |
261 return true; | |
262 | |
263 base::AutoLock lock(any_thread_lock_); | |
264 return any_thread().immediate_incoming_queue.erase(fake_task) > 0; | |
265 } else { | |
266 // It's a delayed task. | |
267 DCHECK_EQ(0ull, handle.enqueue_order_); | |
268 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
Sami
2016/08/18 15:53:43
Readability suggestion -- feel free to ignore: Sho
alex clarke (OOO till 29th)
2016/08/18 16:51:41
Done.
| |
269 handle.sequence_number_, false); | |
270 DelayedRunTimeQueue::iterator it = | |
271 main_thread_only().delayed_incoming_queue.find(fake_task); | |
272 if (it != main_thread_only().delayed_incoming_queue.end()) { | |
273 // It's safe to remove the wakeup from the TimeDomain only if this task's | |
274 // scheduled run time was unique within the queue. | |
275 bool can_cancel_timedomain_wakeup = true; | |
276 if (it != main_thread_only().delayed_incoming_queue.begin()) { | |
277 DelayedRunTimeQueue::iterator before = it; | |
278 before--; | |
279 if (before->delayed_run_time == handle.scheduled_run_time_) | |
280 can_cancel_timedomain_wakeup = false; | |
281 } | |
282 if (can_cancel_timedomain_wakeup) { | |
283 DelayedRunTimeQueue::iterator after = it; | |
284 after++; | |
285 if (after != main_thread_only().delayed_incoming_queue.end() && | |
286 after->delayed_run_time == handle.scheduled_run_time_) { | |
287 can_cancel_timedomain_wakeup = false; | |
288 } | |
289 } | |
290 if (can_cancel_timedomain_wakeup) { | |
291 main_thread_only().time_domain->CancelDelayedWork( | |
292 this, handle.scheduled_run_time_); | |
293 } | |
294 | |
295 main_thread_only().delayed_incoming_queue.erase(it); | |
296 return true; | |
297 } | |
298 | |
299 return main_thread_only().delayed_work_queue->CancelTask(fake_task); | |
300 } | |
301 } | |
302 | |
303 bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const { | |
304 if (!handle) | |
305 return false; | |
306 | |
307 // If the TaskQueueManager has gone away the task got cancelled. | |
308 if (!main_thread_only().task_queue_manager) | |
309 return false; | |
310 | |
311 #if DCHECK_IS_ON() | |
312 DCHECK_EQ(handle.task_queue_, this); | |
313 #endif | |
314 | |
315 if (handle.scheduled_run_time_.is_null()) { | |
316 // It's an immediate task. | |
317 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
318 handle.sequence_number_, false, handle.enqueue_order_); | |
319 if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task)) | |
320 return true; | |
321 | |
322 base::AutoLock lock(any_thread_lock_); | |
323 return any_thread().immediate_incoming_queue.find(fake_task) != | |
324 any_thread().immediate_incoming_queue.end(); | |
325 } else { | |
326 // It's a delayed task. | |
327 DCHECK_EQ(0ull, handle.enqueue_order_); | |
328 Task fake_task(FROM_HERE, base::Closure(), handle.scheduled_run_time_, | |
329 handle.sequence_number_, false); | |
330 DelayedRunTimeQueue::iterator it = | |
331 main_thread_only().delayed_incoming_queue.find(fake_task); | |
332 if (it != main_thread_only().delayed_incoming_queue.end()) | |
333 return true; | |
334 | |
335 return main_thread_only().delayed_work_queue->IsTaskPending(fake_task); | |
336 } | |
337 } | |
338 | |
142 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, | 339 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, |
143 const base::Closure& task, | 340 const base::Closure& task, |
144 base::TimeDelta delay) { | 341 base::TimeDelta delay) { |
145 if (delay.is_zero()) | 342 if (delay.is_zero()) |
146 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); | 343 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); |
147 | 344 |
148 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); | 345 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); |
149 } | 346 } |
150 | 347 |
151 bool TaskQueueImpl::PostNonNestableDelayedTask( | 348 bool TaskQueueImpl::PostNonNestableDelayedTask( |
(...skipping 64 matching lines...) Loading... | |
216 return true; | 413 return true; |
217 } | 414 } |
218 | 415 |
219 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( | 416 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( |
220 Task pending_task, | 417 Task pending_task, |
221 base::TimeTicks now) { | 418 base::TimeTicks now) { |
222 main_thread_only().task_queue_manager->DidQueueTask(pending_task); | 419 main_thread_only().task_queue_manager->DidQueueTask(pending_task); |
223 | 420 |
224 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. | 421 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. |
225 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 422 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
226 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 423 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
227 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 424 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, |
228 now); | 425 now); |
229 TraceQueueSize(false); | 426 TraceQueueSize(false); |
230 } | 427 } |
231 | 428 |
232 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 429 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
233 any_thread().task_queue_manager->DidQueueTask(pending_task); | 430 any_thread().task_queue_manager->DidQueueTask(pending_task); |
234 | 431 |
235 int thread_hop_task_sequence_number = | 432 int thread_hop_task_sequence_number = |
236 any_thread().task_queue_manager->GetNextSequenceNumber(); | 433 any_thread().task_queue_manager->GetNextSequenceNumber(); |
237 PushOntoImmediateIncomingQueueLocked( | 434 PushOntoImmediateIncomingQueueLocked( |
238 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 435 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
239 base::Passed(&pending_task)), | 436 base::Passed(&pending_task)), |
240 base::TimeTicks(), thread_hop_task_sequence_number, false, | 437 base::TimeTicks(), thread_hop_task_sequence_number, false, |
241 thread_hop_task_sequence_number)); | 438 thread_hop_task_sequence_number)); |
242 } | 439 } |
243 | 440 |
244 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 441 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
245 if (any_thread().immediate_incoming_queue.empty()) | 442 if (any_thread().immediate_incoming_queue.empty()) |
246 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 443 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
247 if (any_thread().pump_policy == PumpPolicy::AUTO && | 444 if (any_thread().pump_policy == PumpPolicy::AUTO && |
248 any_thread().immediate_incoming_queue.empty()) { | 445 any_thread().immediate_incoming_queue.empty()) { |
249 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 446 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
250 } | 447 } |
251 any_thread().task_queue_manager->DidQueueTask(pending_task); | 448 any_thread().task_queue_manager->DidQueueTask(pending_task); |
252 any_thread().immediate_incoming_queue.push(std::move(pending_task)); | 449 any_thread().immediate_incoming_queue.insert(std::move(pending_task)); |
253 TraceQueueSize(true); | 450 TraceQueueSize(true); |
254 } | 451 } |
255 | 452 |
256 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { | 453 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { |
257 DCHECK(main_thread_checker_.CalledOnValidThread()); | 454 DCHECK(main_thread_checker_.CalledOnValidThread()); |
258 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; | 455 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; |
259 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); | 456 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); |
260 main_thread_only().time_domain->ScheduleDelayedWork( | 457 main_thread_only().time_domain->ScheduleDelayedWork( |
261 this, delayed_run_time, main_thread_only().time_domain->Now()); | 458 this, delayed_run_time, main_thread_only().time_domain->Now()); |
262 } | 459 } |
263 | 460 |
264 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 461 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
265 if (main_thread_only().is_enabled == enabled) | 462 if (main_thread_only().is_enabled == enabled) |
266 return; | 463 return; |
267 main_thread_only().is_enabled = enabled; | 464 main_thread_only().is_enabled = enabled; |
268 if (!main_thread_only().task_queue_manager) | 465 if (!main_thread_only().task_queue_manager) |
269 return; | 466 return; |
(...skipping 34 matching lines...) Loading... | |
304 | 501 |
305 base::AutoLock lock(any_thread_lock_); | 502 base::AutoLock lock(any_thread_lock_); |
306 if (!any_thread().immediate_incoming_queue.empty()) | 503 if (!any_thread().immediate_incoming_queue.empty()) |
307 return true; | 504 return true; |
308 | 505 |
309 // If there's no immediate Incoming work then we only need pumping if there | 506 // If there's no immediate Incoming work then we only need pumping if there |
310 // is a delayed task that should be running now. | 507 // is a delayed task that should be running now. |
311 if (main_thread_only().delayed_incoming_queue.empty()) | 508 if (main_thread_only().delayed_incoming_queue.empty()) |
312 return false; | 509 return false; |
313 | 510 |
314 return main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 511 return main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
315 main_thread_only().time_domain->CreateLazyNow().Now(); | 512 main_thread_only().time_domain->CreateLazyNow().Now(); |
316 } | 513 } |
317 | 514 |
318 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( | 515 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( |
319 const Task* task) { | 516 const Task* task) { |
320 // A null task is passed when UpdateQueue is called before any task is run. | 517 // A null task is passed when UpdateQueue is called before any task is run. |
321 // In this case we don't want to pump an after_wakeup queue, so return true | 518 // In this case we don't want to pump an after_wakeup queue, so return true |
322 // here. | 519 // here. |
323 if (!task) | 520 if (!task) |
324 return true; | 521 return true; |
325 | 522 |
326 // Return false if task is newer than the oldest immediate task. | 523 // Return false if task is newer than the oldest immediate task. |
327 if (!any_thread().immediate_incoming_queue.empty() && | 524 if (!any_thread().immediate_incoming_queue.empty() && |
328 task->enqueue_order() > | 525 task->enqueue_order() > |
329 any_thread().immediate_incoming_queue.front().enqueue_order()) { | 526 any_thread().immediate_incoming_queue.begin()->enqueue_order()) { |
330 return false; | 527 return false; |
331 } | 528 } |
332 return true; | 529 return true; |
333 } | 530 } |
334 | 531 |
335 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { | 532 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { |
336 DCHECK(main_thread_checker_.CalledOnValidThread()); | 533 DCHECK(main_thread_checker_.CalledOnValidThread()); |
337 // A null task is passed when UpdateQueue is called before any task is run. | 534 // A null task is passed when UpdateQueue is called before any task is run. |
338 // In this case we don't want to pump an after_wakeup queue, so return true | 535 // In this case we don't want to pump an after_wakeup queue, so return true |
339 // here. | 536 // here. |
(...skipping 27 matching lines...) Loading... | |
367 return false; | 564 return false; |
368 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | 565 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && |
369 (!should_trigger_wakeup || | 566 (!should_trigger_wakeup || |
370 TaskIsOlderThanQueuedDelayedTasks(previous_task))) | 567 TaskIsOlderThanQueuedDelayedTasks(previous_task))) |
371 return false; | 568 return false; |
372 return true; | 569 return true; |
373 } | 570 } |
374 | 571 |
375 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 572 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
376 // Enqueue all delayed tasks that should be running now. | 573 // Enqueue all delayed tasks that should be running now. |
377 while (!main_thread_only().delayed_incoming_queue.empty() && | 574 while (!main_thread_only().delayed_incoming_queue.empty()) { |
378 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= | 575 DelayedRunTimeQueue::iterator next_task = |
379 lazy_now->Now()) { | 576 main_thread_only().delayed_incoming_queue.begin(); |
380 // Note: the const_cast is needed because there is no direct way to move | 577 if (next_task->delayed_run_time > lazy_now->Now()) |
381 // elements out of a priority queue. The queue must not be modified between | 578 break; |
382 // the top() and the pop(). | 579 // TODO(alexclarke): Use extract() when C++17 is allowed. |
383 main_thread_only().delayed_work_queue->PushAndSetEnqueueOrder( | 580 Task& task = const_cast<Task&>(*next_task); |
384 std::move( | 581 task.set_enqueue_order( |
385 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())), | |
386 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 582 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
387 main_thread_only().delayed_incoming_queue.pop(); | 583 main_thread_only().delayed_work_queue->Push(std::move(task)); |
584 main_thread_only().delayed_incoming_queue.erase(next_task); | |
388 } | 585 } |
389 } | 586 } |
390 | 587 |
391 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, | 588 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, |
392 bool should_trigger_wakeup, | 589 bool should_trigger_wakeup, |
393 const Task* previous_task) { | 590 const Task* previous_task) { |
394 if (!main_thread_only().task_queue_manager) | 591 if (!main_thread_only().task_queue_manager) |
395 return; | 592 return; |
396 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) | 593 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) |
397 return; | 594 return; |
(...skipping 62 matching lines...) Loading... | |
460 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { | 657 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { |
461 TRACE_EVENT1(disabled_by_default_tracing_category_, | 658 TRACE_EVENT1(disabled_by_default_tracing_category_, |
462 "TaskQueueImpl::PumpQueueLocked", "queue", name_); | 659 "TaskQueueImpl::PumpQueueLocked", "queue", name_); |
463 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; | 660 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; |
464 if (!task_queue_manager) | 661 if (!task_queue_manager) |
465 return; | 662 return; |
466 | 663 |
467 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 664 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
468 | 665 |
469 while (!any_thread().immediate_incoming_queue.empty()) { | 666 while (!any_thread().immediate_incoming_queue.empty()) { |
667 ComparatorQueue::iterator it = | |
668 any_thread().immediate_incoming_queue.begin(); | |
470 main_thread_only().immediate_work_queue->Push( | 669 main_thread_only().immediate_work_queue->Push( |
471 std::move(any_thread().immediate_incoming_queue.front())); | 670 std::move(const_cast<Task&>(*it))); |
472 any_thread().immediate_incoming_queue.pop(); | 671 any_thread().immediate_incoming_queue.erase(it); |
473 } | 672 } |
474 | 673 |
475 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no | 674 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no |
476 // longer needs to consider this queue for reloading. | 675 // longer needs to consider this queue for reloading. |
477 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 676 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
478 | 677 |
479 if (main_thread_only().immediate_work_queue->Empty() && | 678 if (main_thread_only().immediate_work_queue->Empty() && |
480 main_thread_only().delayed_work_queue->Empty()) { | 679 main_thread_only().delayed_work_queue->Empty()) { |
481 return; | 680 return; |
482 } | 681 } |
(...skipping 86 matching lines...) Loading... | |
569 state->SetInteger("immediate_incoming_queue_size", | 768 state->SetInteger("immediate_incoming_queue_size", |
570 any_thread().immediate_incoming_queue.size()); | 769 any_thread().immediate_incoming_queue.size()); |
571 state->SetInteger("delayed_incoming_queue_size", | 770 state->SetInteger("delayed_incoming_queue_size", |
572 main_thread_only().delayed_incoming_queue.size()); | 771 main_thread_only().delayed_incoming_queue.size()); |
573 state->SetInteger("immediate_work_queue_size", | 772 state->SetInteger("immediate_work_queue_size", |
574 main_thread_only().immediate_work_queue->Size()); | 773 main_thread_only().immediate_work_queue->Size()); |
575 state->SetInteger("delayed_work_queue_size", | 774 state->SetInteger("delayed_work_queue_size", |
576 main_thread_only().delayed_work_queue->Size()); | 775 main_thread_only().delayed_work_queue->Size()); |
577 if (!main_thread_only().delayed_incoming_queue.empty()) { | 776 if (!main_thread_only().delayed_incoming_queue.empty()) { |
578 base::TimeDelta delay_to_next_task = | 777 base::TimeDelta delay_to_next_task = |
579 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - | 778 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time - |
580 main_thread_only().time_domain->CreateLazyNow().Now()); | 779 main_thread_only().time_domain->CreateLazyNow().Now()); |
581 state->SetDouble("delay_to_next_task_ms", | 780 state->SetDouble("delay_to_next_task_ms", |
582 delay_to_next_task.InMillisecondsF()); | 781 delay_to_next_task.InMillisecondsF()); |
583 } | 782 } |
584 if (verbose_tracing_enabled) { | 783 if (verbose_tracing_enabled) { |
585 state->BeginArray("immediate_incoming_queue"); | 784 state->BeginArray("immediate_incoming_queue"); |
586 QueueAsValueInto(any_thread().immediate_incoming_queue, state); | 785 QueueAsValueInto(any_thread().immediate_incoming_queue, state); |
587 state->EndArray(); | 786 state->EndArray(); |
588 state->BeginArray("delayed_work_queue"); | 787 state->BeginArray("delayed_work_queue"); |
589 main_thread_only().delayed_work_queue->AsValueInto(state); | 788 main_thread_only().delayed_work_queue->AsValueInto(state); |
(...skipping 65 matching lines...) Loading... | |
655 base::AutoLock lock(any_thread_lock_); | 854 base::AutoLock lock(any_thread_lock_); |
656 return any_thread().time_domain; | 855 return any_thread().time_domain; |
657 } | 856 } |
658 | 857 |
659 void TaskQueueImpl::SetBlameContext( | 858 void TaskQueueImpl::SetBlameContext( |
660 base::trace_event::BlameContext* blame_context) { | 859 base::trace_event::BlameContext* blame_context) { |
661 main_thread_only().blame_context = blame_context; | 860 main_thread_only().blame_context = blame_context; |
662 } | 861 } |
663 | 862 |
664 // static | 863 // static |
665 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, | 864 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
666 base::trace_event::TracedValue* state) { | 865 base::trace_event::TracedValue* state) { |
667 // Remove const to search |queue| in the destructive manner. Restore the | 866 for (const Task& task : queue) { |
668 // content from |visited| later. | 867 TaskAsValueInto(task, state); |
669 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue); | |
670 std::queue<Task> visited; | |
671 while (!mutable_queue->empty()) { | |
672 TaskAsValueInto(mutable_queue->front(), state); | |
673 visited.push(std::move(mutable_queue->front())); | |
674 mutable_queue->pop(); | |
675 } | 868 } |
676 *mutable_queue = std::move(visited); | |
677 } | 869 } |
678 | 870 |
679 // static | 871 // static |
680 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, | 872 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
681 base::trace_event::TracedValue* state) { | 873 base::trace_event::TracedValue* state) { |
682 // Remove const to search |queue| in the destructive manner. Restore the | 874 for (const Task& task : queue) { |
683 // content from |visited| later. | 875 TaskAsValueInto(task, state); |
684 std::priority_queue<Task>* mutable_queue = | |
685 const_cast<std::priority_queue<Task>*>(&queue); | |
686 std::priority_queue<Task> visited; | |
687 while (!mutable_queue->empty()) { | |
688 TaskAsValueInto(mutable_queue->top(), state); | |
689 visited.push(std::move(const_cast<Task&>(mutable_queue->top()))); | |
690 mutable_queue->pop(); | |
691 } | 876 } |
692 *mutable_queue = std::move(visited); | |
693 } | 877 } |
694 | 878 |
695 // static | 879 // static |
696 void TaskQueueImpl::TaskAsValueInto(const Task& task, | 880 void TaskQueueImpl::TaskAsValueInto(const Task& task, |
697 base::trace_event::TracedValue* state) { | 881 base::trace_event::TracedValue* state) { |
698 state->BeginDictionary(); | 882 state->BeginDictionary(); |
699 state->SetString("posted_from", task.posted_from.ToString()); | 883 state->SetString("posted_from", task.posted_from.ToString()); |
700 #ifndef NDEBUG | 884 #ifndef NDEBUG |
701 if (task.enqueue_order_set()) | 885 if (task.enqueue_order_set()) |
702 state->SetInteger("enqueue_order", task.enqueue_order()); | 886 state->SetInteger("enqueue_order", task.enqueue_order()); |
703 #else | 887 #else |
704 state->SetInteger("enqueue_order", task.enqueue_order()); | 888 state->SetInteger("enqueue_order", task.enqueue_order()); |
705 #endif | 889 #endif |
706 state->SetInteger("sequence_num", task.sequence_num); | 890 state->SetInteger("sequence_num", task.sequence_num); |
707 state->SetBoolean("nestable", task.nestable); | 891 state->SetBoolean("nestable", task.nestable); |
708 state->SetBoolean("is_high_res", task.is_high_res); | 892 state->SetBoolean("is_high_res", task.is_high_res); |
709 state->SetDouble( | 893 state->SetDouble( |
710 "delayed_run_time", | 894 "delayed_run_time", |
711 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 895 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
712 state->EndDictionary(); | 896 state->EndDictionary(); |
713 } | 897 } |
714 | 898 |
715 } // namespace internal | 899 } // namespace internal |
716 } // namespace scheduler | 900 } // namespace scheduler |
717 } // namespace blink | 901 } // namespace blink |
OLD | NEW |