Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

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: Various comment nits addressed Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
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...) Expand 10 before | Expand all | Expand 10 after
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 // static
124 TaskQueueImpl::Task TaskQueueImpl::Task::CreateFakeTaskFromHandle(
125 const TaskHandle& handle) {
126 if (handle.scheduled_run_time_.is_null()) {
127 // It's an immediate task.
128 return Task(tracked_objects::Location(), base::Closure(),
129 handle.scheduled_run_time_, handle.sequence_number_, false,
130 handle.enqueue_order_);
131 } else {
132 // It's a delayed task.
133 DCHECK_EQ(0ull, handle.enqueue_order_);
134 return Task(tracked_objects::Location(), base::Closure(),
135 handle.scheduled_run_time_, handle.sequence_number_, false);
136 }
137 }
138
139 bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()(
140 const Task& a,
141 const Task& b) const {
142 if (a.delayed_run_time < b.delayed_run_time)
143 return true;
144
145 if (a.delayed_run_time > b.delayed_run_time)
146 return false;
147
148 // If the times happen to match, then we use the sequence number to decide.
149 // Compare the difference to support integer roll-over.
150 return (a.sequence_num - b.sequence_num) < 0;
151 }
152
153 // static
154 bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a,
155 const Task& b) {
156 return a.enqueue_order() < b.enqueue_order();
157 }
158
159 // static
160 bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a,
161 const Task& b) {
162 if (a.delayed_run_time < b.delayed_run_time)
163 return true;
164
165 if (a.delayed_run_time > b.delayed_run_time)
166 return false;
167
168 // If the times happen to match, then we use the sequence number to decide.
169 // Compare the difference to support integer roll-over.
170 return (a.sequence_num - b.sequence_num) < 0;
171 }
172
94 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, 173 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager,
95 PumpPolicy pump_policy, 174 PumpPolicy pump_policy,
96 TimeDomain* time_domain) 175 TimeDomain* time_domain)
97 : task_queue_manager(task_queue_manager), 176 : task_queue_manager(task_queue_manager),
98 pump_policy(pump_policy), 177 pump_policy(pump_policy),
99 time_domain(time_domain) {} 178 time_domain(time_domain),
179 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) {
180 }
100 181
101 TaskQueueImpl::AnyThread::~AnyThread() {} 182 TaskQueueImpl::AnyThread::~AnyThread() {}
102 183
103 TaskQueueImpl::MainThreadOnly::MainThreadOnly( 184 TaskQueueImpl::MainThreadOnly::MainThreadOnly(
104 TaskQueueManager* task_queue_manager, 185 TaskQueueManager* task_queue_manager,
105 PumpPolicy pump_policy, 186 PumpPolicy pump_policy,
106 TaskQueueImpl* task_queue, 187 TaskQueueImpl* task_queue,
107 TimeDomain* time_domain) 188 TimeDomain* time_domain)
108 : task_queue_manager(task_queue_manager), 189 : task_queue_manager(task_queue_manager),
109 pump_policy(pump_policy), 190 pump_policy(pump_policy),
110 time_domain(time_domain), 191 time_domain(time_domain),
111 delayed_work_queue(new WorkQueue(task_queue, "delayed")), 192 delayed_work_queue(
112 immediate_work_queue(new WorkQueue(task_queue, "immediate")), 193 new WorkQueue(task_queue,
194 "delayed",
195 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)),
196 immediate_work_queue(
197 new WorkQueue(task_queue,
198 "immediate",
199 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)),
113 set_index(0), 200 set_index(0),
114 is_enabled(true), 201 is_enabled(true),
115 blame_context(nullptr) {} 202 blame_context(nullptr) {}
116 203
117 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} 204 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
118 205
119 void TaskQueueImpl::UnregisterTaskQueue() { 206 void TaskQueueImpl::UnregisterTaskQueue() {
120 base::AutoLock lock(any_thread_lock_); 207 base::AutoLock lock(any_thread_lock_);
121 if (main_thread_only().time_domain) 208 if (main_thread_only().time_domain)
122 main_thread_only().time_domain->UnregisterQueue(this); 209 main_thread_only().time_domain->UnregisterQueue(this);
123 if (!any_thread().task_queue_manager) 210 if (!any_thread().task_queue_manager)
124 return; 211 return;
125 any_thread().time_domain = nullptr; 212 any_thread().time_domain = nullptr;
126 main_thread_only().time_domain = nullptr; 213 main_thread_only().time_domain = nullptr;
127 any_thread().task_queue_manager->UnregisterTaskQueue(this); 214 any_thread().task_queue_manager->UnregisterTaskQueue(this);
128 215
129 any_thread().task_queue_manager = nullptr; 216 any_thread().task_queue_manager = nullptr;
130 main_thread_only().task_queue_manager = nullptr; 217 main_thread_only().task_queue_manager = nullptr;
131 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>(); 218 main_thread_only().delayed_incoming_queue.clear();
132 any_thread().immediate_incoming_queue = std::queue<Task>(); 219 any_thread().immediate_incoming_queue.clear();
133 main_thread_only().immediate_work_queue.reset(); 220 main_thread_only().immediate_work_queue.reset();
134 main_thread_only().delayed_work_queue.reset(); 221 main_thread_only().delayed_work_queue.reset();
135 } 222 }
136 223
137 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { 224 bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
138 base::AutoLock lock(any_thread_lock_); 225 base::AutoLock lock(any_thread_lock_);
139 return base::PlatformThread::CurrentId() == thread_id_; 226 return base::PlatformThread::CurrentId() == thread_id_;
140 } 227 }
141 228
229 TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask(
230 const tracked_objects::Location& from_here,
231 const base::Closure& task,
232 base::TimeDelta delay) {
233 if (!main_thread_only().task_queue_manager)
234 return TaskHandle();
235
236 EnqueueOrder sequence_number =
237 main_thread_only().task_queue_manager->GetNextSequenceNumber();
238
239 if (delay.is_zero()) {
240 base::AutoLock lock(any_thread_lock_);
241 PushOntoImmediateIncomingQueueLocked(
242 Task(from_here, task, base::TimeTicks(), sequence_number, true,
243 sequence_number));
244
245 return TaskHandle(this, sequence_number);
246 } else {
247 DCHECK_GT(delay, base::TimeDelta());
248 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
249 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
250 PushOntoDelayedIncomingQueueFromMainThread(
251 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
252 true),
253 time_domain_now);
254
255 return TaskHandle(this, time_domain_delayed_run_time, sequence_number);
256 }
257 }
258
259 bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) {
260 if (!handle)
261 return false;
262
263 // If the TaskQueueManager has gone away, pretend we have canceled the task
264 // because this simplifies logic in TimerBase::stop.
265 if (!main_thread_only().task_queue_manager)
266 return true;
267
268 #if DCHECK_IS_ON()
269 DCHECK_EQ(handle.task_queue_, this);
270 #endif
271
272 Task fake_task = Task::CreateFakeTaskFromHandle(handle);
273 if (handle.scheduled_run_time_.is_null()) {
274 // It's an immediate task.
275 if (main_thread_only().immediate_work_queue->CancelTask(fake_task))
276 return true;
277
278 base::AutoLock lock(any_thread_lock_);
279 return any_thread().immediate_incoming_queue.erase(fake_task) > 0;
280 } else {
281 // It's a delayed task.
282 DelayedRunTimeQueue::iterator it =
283 main_thread_only().delayed_incoming_queue.find(fake_task);
284 if (it != main_thread_only().delayed_incoming_queue.end()) {
285 // It's safe to remove the wakeup from the TimeDomain only if this task's
286 // scheduled run time was unique within the queue.
287 bool can_cancel_timedomain_wakeup = true;
288 if (it != main_thread_only().delayed_incoming_queue.begin()) {
289 DelayedRunTimeQueue::iterator before = it;
290 before--;
291 if (before->delayed_run_time == handle.scheduled_run_time_)
292 can_cancel_timedomain_wakeup = false;
293 }
294 if (can_cancel_timedomain_wakeup) {
295 DelayedRunTimeQueue::iterator after = it;
296 after++;
297 if (after != main_thread_only().delayed_incoming_queue.end() &&
298 after->delayed_run_time == handle.scheduled_run_time_) {
299 can_cancel_timedomain_wakeup = false;
300 }
301 }
302 if (can_cancel_timedomain_wakeup) {
303 main_thread_only().time_domain->CancelDelayedWork(
304 this, handle.scheduled_run_time_);
305 }
306
307 main_thread_only().delayed_incoming_queue.erase(it);
308 return true;
309 }
310
311 return main_thread_only().delayed_work_queue->CancelTask(fake_task);
312 }
313 }
314
315 bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const {
316 if (!handle)
317 return false;
318
319 // If the TaskQueueManager has gone away the task got cancelled.
320 if (!main_thread_only().task_queue_manager)
321 return false;
322
323 #if DCHECK_IS_ON()
324 DCHECK_EQ(handle.task_queue_, this);
325 #endif
326
327 Task fake_task = Task::CreateFakeTaskFromHandle(handle);
328 if (handle.scheduled_run_time_.is_null()) {
329 // It's an immediate task.
330 if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task))
331 return true;
332
333 base::AutoLock lock(any_thread_lock_);
334 return any_thread().immediate_incoming_queue.find(fake_task) !=
335 any_thread().immediate_incoming_queue.end();
336 } else {
337 // It's a delayed task.
338 DelayedRunTimeQueue::iterator it =
339 main_thread_only().delayed_incoming_queue.find(fake_task);
340 if (it != main_thread_only().delayed_incoming_queue.end())
341 return true;
342
343 return main_thread_only().delayed_work_queue->IsTaskPending(fake_task);
344 }
345 }
346
142 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, 347 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
143 const base::Closure& task, 348 const base::Closure& task,
144 base::TimeDelta delay) { 349 base::TimeDelta delay) {
145 if (delay.is_zero()) 350 if (delay.is_zero())
146 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); 351 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
147 352
148 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); 353 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
149 } 354 }
150 355
151 bool TaskQueueImpl::PostNonNestableDelayedTask( 356 bool TaskQueueImpl::PostNonNestableDelayedTask(
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 return true; 421 return true;
217 } 422 }
218 423
219 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( 424 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
220 Task pending_task, 425 Task pending_task,
221 base::TimeTicks now) { 426 base::TimeTicks now) {
222 main_thread_only().task_queue_manager->DidQueueTask(pending_task); 427 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
223 428
224 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. 429 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue.
225 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 430 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
226 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 431 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task));
227 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, 432 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time,
228 now); 433 now);
229 TraceQueueSize(false); 434 TraceQueueSize(false);
230 } 435 }
231 436
232 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { 437 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
233 any_thread().task_queue_manager->DidQueueTask(pending_task); 438 any_thread().task_queue_manager->DidQueueTask(pending_task);
234 439
235 int thread_hop_task_sequence_number = 440 int thread_hop_task_sequence_number =
236 any_thread().task_queue_manager->GetNextSequenceNumber(); 441 any_thread().task_queue_manager->GetNextSequenceNumber();
237 PushOntoImmediateIncomingQueueLocked( 442 PushOntoImmediateIncomingQueueLocked(
238 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, 443 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this,
239 base::Passed(&pending_task)), 444 base::Passed(&pending_task)),
240 base::TimeTicks(), thread_hop_task_sequence_number, false, 445 base::TimeTicks(), thread_hop_task_sequence_number, false,
241 thread_hop_task_sequence_number)); 446 thread_hop_task_sequence_number));
242 } 447 }
243 448
244 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { 449 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) {
245 if (any_thread().immediate_incoming_queue.empty()) 450 if (any_thread().immediate_incoming_queue.empty())
246 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); 451 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
247 if (any_thread().pump_policy == PumpPolicy::AUTO && 452 if (any_thread().pump_policy == PumpPolicy::AUTO &&
248 any_thread().immediate_incoming_queue.empty()) { 453 any_thread().immediate_incoming_queue.empty()) {
249 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
250 } 455 }
251 any_thread().task_queue_manager->DidQueueTask(pending_task); 456 any_thread().task_queue_manager->DidQueueTask(pending_task);
252 any_thread().immediate_incoming_queue.push(std::move(pending_task)); 457 // We expect |pending_task| to be inserted at the end. Amoritized O(1).
458 any_thread().immediate_incoming_queue.insert(
459 any_thread().immediate_incoming_queue.end(),
460 std::move(pending_task));
461 DCHECK_EQ(pending_task.enqueue_order(),
462 any_thread().immediate_incoming_queue.rbegin()->enqueue_order());
253 TraceQueueSize(true); 463 TraceQueueSize(true);
254 } 464 }
255 465
256 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { 466 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
257 DCHECK(main_thread_checker_.CalledOnValidThread()); 467 DCHECK(main_thread_checker_.CalledOnValidThread());
258 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 468 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
259 main_thread_only().delayed_incoming_queue.push(std::move(pending_task)); 469 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
260 main_thread_only().time_domain->ScheduleDelayedWork( 470 // Make sure |delayed_run_time| isn't in the past.
261 this, delayed_run_time, main_thread_only().time_domain->Now()); 471 if (delayed_run_time < time_domain_now) {
472 delayed_run_time = time_domain_now;
473 pending_task.delayed_run_time = time_domain_now;
474 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task));
475 LazyNow lazy_now(time_domain_now);
476 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now);
477 } else {
478 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task));
479 main_thread_only().time_domain->ScheduleDelayedWork(
480 this, delayed_run_time, main_thread_only().time_domain->Now());
481 }
482 TraceQueueSize(false);
262 } 483 }
263 484
264 void TaskQueueImpl::SetQueueEnabled(bool enabled) { 485 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
265 if (main_thread_only().is_enabled == enabled) 486 if (main_thread_only().is_enabled == enabled)
266 return; 487 return;
267 main_thread_only().is_enabled = enabled; 488 main_thread_only().is_enabled = enabled;
268 if (!main_thread_only().task_queue_manager) 489 if (!main_thread_only().task_queue_manager)
269 return; 490 return;
270 if (enabled) { 491 if (enabled) {
271 main_thread_only().task_queue_manager->selector_.EnableQueue(this); 492 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 525
305 base::AutoLock lock(any_thread_lock_); 526 base::AutoLock lock(any_thread_lock_);
306 if (!any_thread().immediate_incoming_queue.empty()) 527 if (!any_thread().immediate_incoming_queue.empty())
307 return true; 528 return true;
308 529
309 // If there's no immediate Incoming work then we only need pumping if there 530 // If there's no immediate Incoming work then we only need pumping if there
310 // is a delayed task that should be running now. 531 // is a delayed task that should be running now.
311 if (main_thread_only().delayed_incoming_queue.empty()) 532 if (main_thread_only().delayed_incoming_queue.empty())
312 return false; 533 return false;
313 534
314 return main_thread_only().delayed_incoming_queue.top().delayed_run_time <= 535 return main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <=
315 main_thread_only().time_domain->CreateLazyNow().Now(); 536 main_thread_only().time_domain->CreateLazyNow().Now();
316 } 537 }
317 538
318 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( 539 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked(
319 const Task* task) { 540 const Task* task) {
320 // A null task is passed when UpdateQueue is called before any task is run. 541 // 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 542 // In this case we don't want to pump an after_wakeup queue, so return true
322 // here. 543 // here.
323 if (!task) 544 if (!task)
324 return true; 545 return true;
325 546
326 // Return false if task is newer than the oldest immediate task. 547 // Return false if task is newer than the oldest immediate task.
327 if (!any_thread().immediate_incoming_queue.empty() && 548 if (!any_thread().immediate_incoming_queue.empty() &&
328 task->enqueue_order() > 549 task->enqueue_order() >
329 any_thread().immediate_incoming_queue.front().enqueue_order()) { 550 any_thread().immediate_incoming_queue.begin()->enqueue_order()) {
330 return false; 551 return false;
331 } 552 }
332 return true; 553 return true;
333 } 554 }
334 555
335 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { 556 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) {
336 DCHECK(main_thread_checker_.CalledOnValidThread()); 557 DCHECK(main_thread_checker_.CalledOnValidThread());
337 // A null task is passed when UpdateQueue is called before any task is run. 558 // 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 559 // In this case we don't want to pump an after_wakeup queue, so return true
339 // here. 560 // here.
(...skipping 27 matching lines...) Expand all
367 return false; 588 return false;
368 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && 589 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP &&
369 (!should_trigger_wakeup || 590 (!should_trigger_wakeup ||
370 TaskIsOlderThanQueuedDelayedTasks(previous_task))) 591 TaskIsOlderThanQueuedDelayedTasks(previous_task)))
371 return false; 592 return false;
372 return true; 593 return true;
373 } 594 }
374 595
375 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { 596 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) {
376 // Enqueue all delayed tasks that should be running now. 597 // Enqueue all delayed tasks that should be running now.
377 while (!main_thread_only().delayed_incoming_queue.empty() && 598 while (!main_thread_only().delayed_incoming_queue.empty()) {
378 main_thread_only().delayed_incoming_queue.top().delayed_run_time <= 599 DelayedRunTimeQueue::iterator next_task =
379 lazy_now->Now()) { 600 main_thread_only().delayed_incoming_queue.begin();
380 // Note: the const_cast is needed because there is no direct way to move 601 if (next_task->delayed_run_time > lazy_now->Now())
381 // elements out of a priority queue. The queue must not be modified between 602 break;
382 // the top() and the pop(). 603 // TODO(alexclarke): Use extract() when C++17 is allowed.
383 main_thread_only().delayed_work_queue->PushAndSetEnqueueOrder( 604 Task& task = const_cast<Task&>(*next_task);
384 std::move( 605 task.set_enqueue_order(
385 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())),
386 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 606 main_thread_only().task_queue_manager->GetNextSequenceNumber());
387 main_thread_only().delayed_incoming_queue.pop(); 607 main_thread_only().delayed_work_queue->Push(std::move(task));
608 main_thread_only().delayed_incoming_queue.erase(next_task);
388 } 609 }
389 } 610 }
390 611
391 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, 612 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now,
392 bool should_trigger_wakeup, 613 bool should_trigger_wakeup,
393 const Task* previous_task) { 614 const Task* previous_task) {
394 if (!main_thread_only().task_queue_manager) 615 if (!main_thread_only().task_queue_manager)
395 return; 616 return;
396 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) 617 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task))
397 return; 618 return;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { 681 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) {
461 TRACE_EVENT1(disabled_by_default_tracing_category_, 682 TRACE_EVENT1(disabled_by_default_tracing_category_,
462 "TaskQueueImpl::PumpQueueLocked", "queue", name_); 683 "TaskQueueImpl::PumpQueueLocked", "queue", name_);
463 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; 684 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager;
464 if (!task_queue_manager) 685 if (!task_queue_manager)
465 return; 686 return;
466 687
467 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); 688 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
468 689
469 while (!any_thread().immediate_incoming_queue.empty()) { 690 while (!any_thread().immediate_incoming_queue.empty()) {
691 ComparatorQueue::iterator it =
692 any_thread().immediate_incoming_queue.begin();
470 main_thread_only().immediate_work_queue->Push( 693 main_thread_only().immediate_work_queue->Push(
471 std::move(any_thread().immediate_incoming_queue.front())); 694 std::move(const_cast<Task&>(*it)));
472 any_thread().immediate_incoming_queue.pop(); 695 any_thread().immediate_incoming_queue.erase(it);
473 } 696 }
474 697
475 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no 698 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no
476 // longer needs to consider this queue for reloading. 699 // longer needs to consider this queue for reloading.
477 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); 700 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
478 701
479 if (main_thread_only().immediate_work_queue->Empty() && 702 if (main_thread_only().immediate_work_queue->Empty() &&
480 main_thread_only().delayed_work_queue->Empty()) { 703 main_thread_only().delayed_work_queue->Empty()) {
481 return; 704 return;
482 } 705 }
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 state->SetInteger("immediate_incoming_queue_size", 792 state->SetInteger("immediate_incoming_queue_size",
570 any_thread().immediate_incoming_queue.size()); 793 any_thread().immediate_incoming_queue.size());
571 state->SetInteger("delayed_incoming_queue_size", 794 state->SetInteger("delayed_incoming_queue_size",
572 main_thread_only().delayed_incoming_queue.size()); 795 main_thread_only().delayed_incoming_queue.size());
573 state->SetInteger("immediate_work_queue_size", 796 state->SetInteger("immediate_work_queue_size",
574 main_thread_only().immediate_work_queue->Size()); 797 main_thread_only().immediate_work_queue->Size());
575 state->SetInteger("delayed_work_queue_size", 798 state->SetInteger("delayed_work_queue_size",
576 main_thread_only().delayed_work_queue->Size()); 799 main_thread_only().delayed_work_queue->Size());
577 if (!main_thread_only().delayed_incoming_queue.empty()) { 800 if (!main_thread_only().delayed_incoming_queue.empty()) {
578 base::TimeDelta delay_to_next_task = 801 base::TimeDelta delay_to_next_task =
579 (main_thread_only().delayed_incoming_queue.top().delayed_run_time - 802 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time -
580 main_thread_only().time_domain->CreateLazyNow().Now()); 803 main_thread_only().time_domain->CreateLazyNow().Now());
581 state->SetDouble("delay_to_next_task_ms", 804 state->SetDouble("delay_to_next_task_ms",
582 delay_to_next_task.InMillisecondsF()); 805 delay_to_next_task.InMillisecondsF());
583 } 806 }
584 if (verbose_tracing_enabled) { 807 if (verbose_tracing_enabled) {
585 state->BeginArray("immediate_incoming_queue"); 808 state->BeginArray("immediate_incoming_queue");
586 QueueAsValueInto(any_thread().immediate_incoming_queue, state); 809 QueueAsValueInto(any_thread().immediate_incoming_queue, state);
587 state->EndArray(); 810 state->EndArray();
588 state->BeginArray("delayed_work_queue"); 811 state->BeginArray("delayed_work_queue");
589 main_thread_only().delayed_work_queue->AsValueInto(state); 812 main_thread_only().delayed_work_queue->AsValueInto(state);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 base::AutoLock lock(any_thread_lock_); 878 base::AutoLock lock(any_thread_lock_);
656 return any_thread().time_domain; 879 return any_thread().time_domain;
657 } 880 }
658 881
659 void TaskQueueImpl::SetBlameContext( 882 void TaskQueueImpl::SetBlameContext(
660 base::trace_event::BlameContext* blame_context) { 883 base::trace_event::BlameContext* blame_context) {
661 main_thread_only().blame_context = blame_context; 884 main_thread_only().blame_context = blame_context;
662 } 885 }
663 886
664 // static 887 // static
665 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue, 888 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue,
666 base::trace_event::TracedValue* state) { 889 base::trace_event::TracedValue* state) {
667 // Remove const to search |queue| in the destructive manner. Restore the 890 for (const Task& task : queue) {
668 // content from |visited| later. 891 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 } 892 }
676 *mutable_queue = std::move(visited);
677 } 893 }
678 894
679 // static 895 // static
680 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue, 896 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue,
681 base::trace_event::TracedValue* state) { 897 base::trace_event::TracedValue* state) {
682 // Remove const to search |queue| in the destructive manner. Restore the 898 for (const Task& task : queue) {
683 // content from |visited| later. 899 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 } 900 }
692 *mutable_queue = std::move(visited);
693 } 901 }
694 902
695 // static 903 // static
696 void TaskQueueImpl::TaskAsValueInto(const Task& task, 904 void TaskQueueImpl::TaskAsValueInto(const Task& task,
697 base::trace_event::TracedValue* state) { 905 base::trace_event::TracedValue* state) {
698 state->BeginDictionary(); 906 state->BeginDictionary();
699 state->SetString("posted_from", task.posted_from.ToString()); 907 state->SetString("posted_from", task.posted_from.ToString());
700 #ifndef NDEBUG 908 #ifndef NDEBUG
701 if (task.enqueue_order_set()) 909 if (task.enqueue_order_set())
702 state->SetInteger("enqueue_order", task.enqueue_order()); 910 state->SetInteger("enqueue_order", task.enqueue_order());
703 #else 911 #else
704 state->SetInteger("enqueue_order", task.enqueue_order()); 912 state->SetInteger("enqueue_order", task.enqueue_order());
705 #endif 913 #endif
706 state->SetInteger("sequence_num", task.sequence_num); 914 state->SetInteger("sequence_num", task.sequence_num);
707 state->SetBoolean("nestable", task.nestable); 915 state->SetBoolean("nestable", task.nestable);
708 state->SetBoolean("is_high_res", task.is_high_res); 916 state->SetBoolean("is_high_res", task.is_high_res);
709 state->SetDouble( 917 state->SetDouble(
710 "delayed_run_time", 918 "delayed_run_time",
711 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 919 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
712 state->EndDictionary(); 920 state->EndDictionary();
713 } 921 }
714 922
715 } // namespace internal 923 } // namespace internal
716 } // namespace scheduler 924 } // namespace scheduler
717 } // namespace blink 925 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698