Chromium Code Reviews

Side by Side Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.cc

Issue 2258713004: Make tasks cancellable inside the blink scheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
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...)
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...)
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...)
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...)
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...)
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...)
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...)
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
OLDNEW

Powered by Google App Engine