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

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

Issue 2319053004: [Reland] Make canceling Timers fast. (Closed)
Patch Set: Rebased Created 4 years, 3 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 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
44 namespace internal { 16 namespace internal {
45 17
46 TaskQueueImpl::TaskQueueImpl( 18 TaskQueueImpl::TaskQueueImpl(
47 TaskQueueManager* task_queue_manager, 19 TaskQueueManager* task_queue_manager,
48 TimeDomain* time_domain, 20 TimeDomain* time_domain,
49 const Spec& spec, 21 const Spec& spec,
50 const char* disabled_by_default_tracing_category, 22 const char* disabled_by_default_tracing_category,
51 const char* disabled_by_default_verbose_tracing_category) 23 const char* disabled_by_default_verbose_tracing_category)
52 : thread_id_(base::PlatformThread::CurrentId()), 24 : thread_id_(base::PlatformThread::CurrentId()),
53 any_thread_(task_queue_manager, time_domain), 25 any_thread_(task_queue_manager, time_domain),
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 bool nestable, 81 bool nestable,
110 EnqueueOrder enqueue_order) 82 EnqueueOrder enqueue_order)
111 : PendingTask(posted_from, task, desired_run_time, nestable), 83 : PendingTask(posted_from, task, desired_run_time, nestable),
112 #ifndef NDEBUG 84 #ifndef NDEBUG
113 enqueue_order_set_(true), 85 enqueue_order_set_(true),
114 #endif 86 #endif
115 enqueue_order_(enqueue_order) { 87 enqueue_order_(enqueue_order) {
116 sequence_num = sequence_number; 88 sequence_num = sequence_number;
117 } 89 }
118 90
119 // static
120 TaskQueueImpl::Task TaskQueueImpl::Task::CreateFakeTaskFromHandle(
121 const TaskHandle& handle) {
122 if (handle.scheduled_run_time_.is_null()) {
123 // It's an immediate task.
124 return Task(tracked_objects::Location(), base::Closure(),
125 handle.scheduled_run_time_, handle.sequence_number_, false,
126 handle.enqueue_order_);
127 } else {
128 // It's a delayed task.
129 DCHECK_EQ(0ull, handle.enqueue_order_);
130 return Task(tracked_objects::Location(), base::Closure(),
131 handle.scheduled_run_time_, handle.sequence_number_, false);
132 }
133 }
134
135 bool TaskQueueImpl::Task::DelayedRunTimeComparator::operator()(
136 const Task& a,
137 const Task& b) const {
138 if (a.delayed_run_time < b.delayed_run_time)
139 return true;
140
141 if (a.delayed_run_time > b.delayed_run_time)
142 return false;
143
144 // If the times happen to match, then we use the sequence number to decide.
145 // Compare the difference to support integer roll-over.
146 return (a.sequence_num - b.sequence_num) < 0;
147 }
148
149 // static
150 bool TaskQueueImpl::Task::EnqueueOrderComparatorFn(const Task& a,
151 const Task& b) {
152 return a.enqueue_order() < b.enqueue_order();
153 }
154
155 // static
156 bool TaskQueueImpl::Task::DelayedRunTimeComparatorFn(const Task& a,
157 const Task& b) {
158 if (a.delayed_run_time < b.delayed_run_time)
159 return true;
160
161 if (a.delayed_run_time > b.delayed_run_time)
162 return false;
163
164 // If the times happen to match, then we use the sequence number to decide.
165 // Compare the difference to support integer roll-over.
166 return (a.sequence_num - b.sequence_num) < 0;
167 }
168
169 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, 91 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager,
170 TimeDomain* time_domain) 92 TimeDomain* time_domain)
171 : task_queue_manager(task_queue_manager), 93 : task_queue_manager(task_queue_manager), time_domain(time_domain) {}
172 time_domain(time_domain),
173 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) {
174 }
175 94
176 TaskQueueImpl::AnyThread::~AnyThread() {} 95 TaskQueueImpl::AnyThread::~AnyThread() {}
177 96
178 TaskQueueImpl::MainThreadOnly::MainThreadOnly( 97 TaskQueueImpl::MainThreadOnly::MainThreadOnly(
179 TaskQueueManager* task_queue_manager, 98 TaskQueueManager* task_queue_manager,
180 TaskQueueImpl* task_queue, 99 TaskQueueImpl* task_queue,
181 TimeDomain* time_domain) 100 TimeDomain* time_domain)
182 : task_queue_manager(task_queue_manager), 101 : task_queue_manager(task_queue_manager),
183 time_domain(time_domain), 102 time_domain(time_domain),
184 delayed_work_queue( 103 delayed_work_queue(new WorkQueue(task_queue, "delayed")),
185 new WorkQueue(task_queue, 104 immediate_work_queue(new WorkQueue(task_queue, "immediate")),
186 "delayed",
187 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)),
188 immediate_work_queue(
189 new WorkQueue(task_queue,
190 "immediate",
191 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)),
192 set_index(0), 105 set_index(0),
193 is_enabled(true), 106 is_enabled(true),
194 blame_context(nullptr), 107 blame_context(nullptr),
195 current_fence(0) {} 108 current_fence(0) {}
196 109
197 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} 110 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
198 111
199 void TaskQueueImpl::UnregisterTaskQueue() { 112 void TaskQueueImpl::UnregisterTaskQueue() {
200 base::AutoLock lock(any_thread_lock_); 113 base::AutoLock lock(any_thread_lock_);
201 if (main_thread_only().time_domain) 114 if (main_thread_only().time_domain)
202 main_thread_only().time_domain->UnregisterQueue(this); 115 main_thread_only().time_domain->UnregisterQueue(this);
203 if (!any_thread().task_queue_manager) 116 if (!any_thread().task_queue_manager)
204 return; 117 return;
205 any_thread().time_domain = nullptr; 118 any_thread().time_domain = nullptr;
206 main_thread_only().time_domain = nullptr; 119 main_thread_only().time_domain = nullptr;
207 any_thread().task_queue_manager->UnregisterTaskQueue(this); 120 any_thread().task_queue_manager->UnregisterTaskQueue(this);
208 121
209 any_thread().task_queue_manager = nullptr; 122 any_thread().task_queue_manager = nullptr;
210 main_thread_only().task_queue_manager = nullptr; 123 main_thread_only().task_queue_manager = nullptr;
211 main_thread_only().delayed_incoming_queue.clear(); 124 main_thread_only().delayed_incoming_queue = std::priority_queue<Task>();
212 any_thread().immediate_incoming_queue.clear(); 125 any_thread().immediate_incoming_queue = std::queue<Task>();
213 main_thread_only().immediate_work_queue.reset(); 126 main_thread_only().immediate_work_queue.reset();
214 main_thread_only().delayed_work_queue.reset(); 127 main_thread_only().delayed_work_queue.reset();
215 } 128 }
216 129
217 bool TaskQueueImpl::RunsTasksOnCurrentThread() const { 130 bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
218 base::AutoLock lock(any_thread_lock_); 131 base::AutoLock lock(any_thread_lock_);
219 return base::PlatformThread::CurrentId() == thread_id_; 132 return base::PlatformThread::CurrentId() == thread_id_;
220 } 133 }
221 134
222 TaskQueue::TaskHandle TaskQueueImpl::PostCancellableDelayedTask(
223 const tracked_objects::Location& from_here,
224 const base::Closure& task,
225 base::TimeDelta delay) {
226 if (!main_thread_only().task_queue_manager)
227 return TaskHandle();
228
229 EnqueueOrder sequence_number =
230 main_thread_only().task_queue_manager->GetNextSequenceNumber();
231
232 if (delay.is_zero()) {
233 base::AutoLock lock(any_thread_lock_);
234 PushOntoImmediateIncomingQueueLocked(
235 Task(from_here, task, base::TimeTicks(), sequence_number, true,
236 sequence_number));
237
238 return TaskHandle(this, sequence_number);
239 } else {
240 DCHECK_GT(delay, base::TimeDelta());
241 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
242 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
243 PushOntoDelayedIncomingQueueFromMainThread(
244 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
245 true),
246 time_domain_now);
247
248 return TaskHandle(this, time_domain_delayed_run_time, sequence_number);
249 }
250 }
251
252 bool TaskQueueImpl::CancelTask(const TaskQueue::TaskHandle& handle) {
253 if (!handle)
254 return false;
255
256 // If the TaskQueueManager has gone away, pretend we have canceled the task
257 // because this simplifies logic in TimerBase::stop.
258 if (!main_thread_only().task_queue_manager)
259 return true;
260
261 #if DCHECK_IS_ON()
262 DCHECK_EQ(handle.task_queue_, this);
263 #endif
264
265 Task fake_task = Task::CreateFakeTaskFromHandle(handle);
266 if (handle.scheduled_run_time_.is_null()) {
267 // It's an immediate task.
268 if (main_thread_only().immediate_work_queue->CancelTask(fake_task))
269 return true;
270
271 base::AutoLock lock(any_thread_lock_);
272 return any_thread().immediate_incoming_queue.erase(fake_task) > 0;
273 } else {
274 // It's a delayed task.
275 DelayedRunTimeQueue::iterator it =
276 main_thread_only().delayed_incoming_queue.find(fake_task);
277 if (it != main_thread_only().delayed_incoming_queue.end()) {
278 // It's safe to remove the wakeup from the TimeDomain only if this task's
279 // scheduled run time was unique within the queue.
280 bool can_cancel_timedomain_wakeup = true;
281 if (it != main_thread_only().delayed_incoming_queue.begin()) {
282 DelayedRunTimeQueue::iterator before = it;
283 before--;
284 if (before->delayed_run_time == handle.scheduled_run_time_)
285 can_cancel_timedomain_wakeup = false;
286 }
287 if (can_cancel_timedomain_wakeup) {
288 DelayedRunTimeQueue::iterator after = it;
289 after++;
290 if (after != main_thread_only().delayed_incoming_queue.end() &&
291 after->delayed_run_time == handle.scheduled_run_time_) {
292 can_cancel_timedomain_wakeup = false;
293 }
294 }
295 if (can_cancel_timedomain_wakeup) {
296 main_thread_only().time_domain->CancelDelayedWork(
297 this, handle.scheduled_run_time_);
298 }
299
300 main_thread_only().delayed_incoming_queue.erase(it);
301 return true;
302 }
303
304 return main_thread_only().delayed_work_queue->CancelTask(fake_task);
305 }
306 }
307
308 bool TaskQueueImpl::IsTaskPending(const TaskQueue::TaskHandle& handle) const {
309 if (!handle)
310 return false;
311
312 // If the TaskQueueManager has gone away the task got cancelled.
313 if (!main_thread_only().task_queue_manager)
314 return false;
315
316 #if DCHECK_IS_ON()
317 DCHECK_EQ(handle.task_queue_, this);
318 #endif
319
320 Task fake_task = Task::CreateFakeTaskFromHandle(handle);
321 if (handle.scheduled_run_time_.is_null()) {
322 // It's an immediate task.
323 if (main_thread_only().immediate_work_queue->IsTaskPending(fake_task))
324 return true;
325
326 base::AutoLock lock(any_thread_lock_);
327 return any_thread().immediate_incoming_queue.find(fake_task) !=
328 any_thread().immediate_incoming_queue.end();
329 } else {
330 // It's a delayed task.
331 DelayedRunTimeQueue::iterator it =
332 main_thread_only().delayed_incoming_queue.find(fake_task);
333 if (it != main_thread_only().delayed_incoming_queue.end())
334 return true;
335
336 return main_thread_only().delayed_work_queue->IsTaskPending(fake_task);
337 }
338 }
339 135
340 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here, 136 bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
341 const base::Closure& task, 137 const base::Closure& task,
342 base::TimeDelta delay) { 138 base::TimeDelta delay) {
343 if (delay.is_zero()) 139 if (delay.is_zero())
344 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL); 140 return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
345 141
346 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL); 142 return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
347 } 143 }
348 144
(...skipping 12 matching lines...) Expand all
361 const base::Closure& task, 157 const base::Closure& task,
362 TaskType task_type) { 158 TaskType task_type) {
363 base::AutoLock lock(any_thread_lock_); 159 base::AutoLock lock(any_thread_lock_);
364 if (!any_thread().task_queue_manager) 160 if (!any_thread().task_queue_manager)
365 return false; 161 return false;
366 162
367 EnqueueOrder sequence_number = 163 EnqueueOrder sequence_number =
368 any_thread().task_queue_manager->GetNextSequenceNumber(); 164 any_thread().task_queue_manager->GetNextSequenceNumber();
369 165
370 PushOntoImmediateIncomingQueueLocked( 166 PushOntoImmediateIncomingQueueLocked(
371 Task(from_here, task, base::TimeTicks(), sequence_number, 167 from_here,
372 task_type != TaskType::NON_NESTABLE, sequence_number)); 168 task,
169 base::TimeTicks(),
170 sequence_number,
171 task_type != TaskType::NON_NESTABLE);
373 return true; 172 return true;
374 } 173 }
375 174
376 bool TaskQueueImpl::PostDelayedTaskImpl( 175 bool TaskQueueImpl::PostDelayedTaskImpl(
377 const tracked_objects::Location& from_here, 176 const tracked_objects::Location& from_here,
378 const base::Closure& task, 177 const base::Closure& task,
379 base::TimeDelta delay, 178 base::TimeDelta delay,
380 TaskType task_type) { 179 TaskType task_type) {
381 DCHECK_GT(delay, base::TimeDelta()); 180 DCHECK_GT(delay, base::TimeDelta());
382 if (base::PlatformThread::CurrentId() == thread_id_) { 181 if (base::PlatformThread::CurrentId() == thread_id_) {
(...skipping 25 matching lines...) Expand all
408 base::TimeTicks time_domain_now = any_thread().time_domain->Now(); 207 base::TimeTicks time_domain_now = any_thread().time_domain->Now();
409 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; 208 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
410 PushOntoDelayedIncomingQueueLocked( 209 PushOntoDelayedIncomingQueueLocked(
411 Task(from_here, task, time_domain_delayed_run_time, sequence_number, 210 Task(from_here, task, time_domain_delayed_run_time, sequence_number,
412 task_type != TaskType::NON_NESTABLE)); 211 task_type != TaskType::NON_NESTABLE));
413 } 212 }
414 return true; 213 return true;
415 } 214 }
416 215
417 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( 216 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
418 Task pending_task, 217 Task pending_task, base::TimeTicks now) {
419 base::TimeTicks now) {
420 main_thread_only().task_queue_manager->DidQueueTask(pending_task); 218 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
421 219
422 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. 220 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue.
423 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 221 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
424 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); 222 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
425 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, 223 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time,
426 now); 224 now);
427 TraceQueueSize(false); 225 TraceQueueSize(false);
428 } 226 }
429 227
430 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { 228 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
431 any_thread().task_queue_manager->DidQueueTask(pending_task); 229 any_thread().task_queue_manager->DidQueueTask(pending_task);
432 230
433 int thread_hop_task_sequence_number = 231 int thread_hop_task_sequence_number =
434 any_thread().task_queue_manager->GetNextSequenceNumber(); 232 any_thread().task_queue_manager->GetNextSequenceNumber();
435 PushOntoImmediateIncomingQueueLocked( 233 PushOntoImmediateIncomingQueueLocked(
436 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, 234 FROM_HERE,
437 base::Passed(&pending_task)), 235 base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this,
438 base::TimeTicks(), thread_hop_task_sequence_number, false, 236 base::Passed(&pending_task)),
439 thread_hop_task_sequence_number)); 237 base::TimeTicks(),
238 thread_hop_task_sequence_number,
239 false);
440 } 240 }
441 241
442 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { 242 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(
243 const tracked_objects::Location& posted_from,
244 const base::Closure& task,
245 base::TimeTicks desired_run_time,
246 EnqueueOrder sequence_number,
247 bool nestable) {
443 if (any_thread().immediate_incoming_queue.empty()) 248 if (any_thread().immediate_incoming_queue.empty())
444 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); 249 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
445 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make 250 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
446 // it run. 251 // it run.
447 if (any_thread().immediate_incoming_queue.empty()) { 252 if (any_thread().immediate_incoming_queue.empty()) {
448 // There's no point posting a DoWork for a disabled queue, however we can 253 // There's no point posting a DoWork for a disabled queue, however we can
449 // only tell if it's disabled from the main thread. 254 // only tell if it's disabled from the main thread.
450 if (base::PlatformThread::CurrentId() == thread_id_) { 255 if (base::PlatformThread::CurrentId() == thread_id_) {
451 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) 256 if (main_thread_only().is_enabled && !BlockedByFenceLocked())
452 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 257 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
453 } else { 258 } else {
454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 259 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
455 } 260 }
456 } 261 }
457 any_thread().task_queue_manager->DidQueueTask(pending_task); 262 any_thread().immediate_incoming_queue.emplace(
458 // We expect |pending_task| to be inserted at the end. Amoritized O(1). 263 posted_from, task, desired_run_time, sequence_number, nestable, sequence_n umber);
459 any_thread().immediate_incoming_queue.insert( 264 any_thread().task_queue_manager->DidQueueTask( any_thread().immediate_incoming _queue.back());
460 any_thread().immediate_incoming_queue.end(),
461 std::move(pending_task));
462 DCHECK_EQ(pending_task.enqueue_order(),
463 any_thread().immediate_incoming_queue.rbegin()->enqueue_order());
464 TraceQueueSize(true); 265 TraceQueueSize(true);
465 } 266 }
466 267
467 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { 268 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
468 DCHECK(main_thread_checker_.CalledOnValidThread()); 269 DCHECK(main_thread_checker_.CalledOnValidThread());
469 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 270 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
470 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); 271 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
471 // Make sure |delayed_run_time| isn't in the past. 272 // Make sure |delayed_run_time| isn't in the past.
472 if (delayed_run_time < time_domain_now) { 273 if (delayed_run_time < time_domain_now) {
473 delayed_run_time = time_domain_now; 274 delayed_run_time = time_domain_now;
474 pending_task.delayed_run_time = time_domain_now; 275 pending_task.delayed_run_time = time_domain_now;
475 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); 276 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
476 LazyNow lazy_now(time_domain_now); 277 LazyNow lazy_now(time_domain_now);
477 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); 278 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now);
478 } else { 279 } else {
479 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); 280 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
480 main_thread_only().time_domain->ScheduleDelayedWork( 281 main_thread_only().time_domain->ScheduleDelayedWork(
481 this, delayed_run_time, main_thread_only().time_domain->Now()); 282 this, delayed_run_time, main_thread_only().time_domain->Now());
482 } 283 }
483 TraceQueueSize(false); 284 TraceQueueSize(false);
484 } 285 }
485 286
486 void TaskQueueImpl::SetQueueEnabled(bool enabled) { 287 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
487 if (main_thread_only().is_enabled == enabled) 288 if (main_thread_only().is_enabled == enabled)
488 return; 289 return;
489 main_thread_only().is_enabled = enabled; 290 main_thread_only().is_enabled = enabled;
490 if (!main_thread_only().task_queue_manager) 291 if (!main_thread_only().task_queue_manager)
491 return; 292 return;
492 if (enabled) { 293 if (enabled) {
493 // Note it's the job of the selector to tell the TaskQueueManager if 294 // Note it's the job of the selector to tell the TaskQueueManager if
494 // a DoWork needs posting. 295 // a DoWork needs posting.
495 main_thread_only().task_queue_manager->selector_.EnableQueue(this); 296 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
496 } else { 297 } else {
497 main_thread_only().task_queue_manager->selector_.DisableQueue(this); 298 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
498 } 299 }
499 } 300 }
500 301
501 bool TaskQueueImpl::IsQueueEnabled() const { 302 bool TaskQueueImpl::IsQueueEnabled() const {
502 return main_thread_only().is_enabled; 303 return main_thread_only().is_enabled;
503 } 304 }
504 305
505 bool TaskQueueImpl::IsEmpty() const { 306 bool TaskQueueImpl::IsEmpty() const {
506 if (!main_thread_only().delayed_work_queue->Empty() || 307 if (!main_thread_only().delayed_work_queue->Empty() ||
308 !main_thread_only().delayed_incoming_queue.empty() ||
507 !main_thread_only().immediate_work_queue->Empty()) { 309 !main_thread_only().immediate_work_queue->Empty()) {
508 return false; 310 return false;
509 } 311 }
510 312
511 base::AutoLock lock(any_thread_lock_); 313 base::AutoLock lock(any_thread_lock_);
512 return any_thread().immediate_incoming_queue.empty() && 314 return any_thread().immediate_incoming_queue.empty();
513 main_thread_only().delayed_incoming_queue.empty();
514 } 315 }
515 316
516 bool TaskQueueImpl::HasPendingImmediateWork() const { 317 bool TaskQueueImpl::HasPendingImmediateWork() const {
517 // Any work queue tasks count as immediate work. 318 // Any work queue tasks count as immediate work.
518 if (!main_thread_only().delayed_work_queue->Empty() || 319 if (!main_thread_only().delayed_work_queue->Empty() ||
519 !main_thread_only().immediate_work_queue->Empty()) { 320 !main_thread_only().immediate_work_queue->Empty()) {
520 return true; 321 return true;
521 } 322 }
522 323
523 // Tasks on |delayed_incoming_queue| that could run now, count as 324 // Tasks on |delayed_incoming_queue| that could run now, count as
524 // immediate work. 325 // immediate work.
525 if (!main_thread_only().delayed_incoming_queue.empty() && 326 if (!main_thread_only().delayed_incoming_queue.empty() &&
526 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= 327 main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
527 main_thread_only().time_domain->CreateLazyNow().Now()) { 328 main_thread_only().time_domain->CreateLazyNow().Now()) {
528 return true; 329 return true;
529 } 330 }
530 331
531 // Finally tasks on |immediate_incoming_queue| count as immediate work. 332 // Finally tasks on |immediate_incoming_queue| count as immediate work.
532 base::AutoLock lock(any_thread_lock_); 333 base::AutoLock lock(any_thread_lock_);
533 return !any_thread().immediate_incoming_queue.empty(); 334 return !any_thread().immediate_incoming_queue.empty();
534 } 335 }
535 336
536 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { 337 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) {
537 // Enqueue all delayed tasks that should be running now. 338 // Enqueue all delayed tasks that should be running now, skipping any that
339 // have been canceled.
538 while (!main_thread_only().delayed_incoming_queue.empty()) { 340 while (!main_thread_only().delayed_incoming_queue.empty()) {
539 DelayedRunTimeQueue::iterator next_task = 341 // TODO(alexclarke): Use extract() when C++17 is allowed.
540 main_thread_only().delayed_incoming_queue.begin(); 342 Task& task =
541 if (next_task->delayed_run_time > lazy_now->Now()) 343 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top());
344 if (task.task.IsCancelled()) {
345 main_thread_only().delayed_incoming_queue.pop();
346 continue;
347 }
348 if (task.delayed_run_time > lazy_now->Now())
542 break; 349 break;
543 // TODO(alexclarke): Use extract() when C++17 is allowed.
544 Task& task = const_cast<Task&>(*next_task);
545 task.set_enqueue_order( 350 task.set_enqueue_order(
546 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 351 main_thread_only().task_queue_manager->GetNextSequenceNumber());
547 main_thread_only().delayed_work_queue->Push(std::move(task)); 352 main_thread_only().delayed_work_queue->Push(std::move(task));
548 main_thread_only().delayed_incoming_queue.erase(next_task); 353 main_thread_only().delayed_incoming_queue.pop();
549 } 354 }
550 } 355 }
551 356
552 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { 357 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() {
553 if (!main_thread_only().task_queue_manager) 358 if (!main_thread_only().task_queue_manager)
554 return; 359 return false;
555 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
556 TraceQueueSize(false);
557 }
558 360
559 void TaskQueueImpl::UpdateImmediateWorkQueue() { 361 if (!main_thread_only().immediate_work_queue->Empty())
560 DCHECK(main_thread_only().immediate_work_queue->Empty()); 362 return true;
363
561 base::AutoLock lock(any_thread_lock_); 364 base::AutoLock lock(any_thread_lock_);
562 if (!main_thread_only().task_queue_manager)
563 return;
564
565 main_thread_only().immediate_work_queue->SwapLocked( 365 main_thread_only().immediate_work_queue->SwapLocked(
566 any_thread().immediate_incoming_queue); 366 any_thread().immediate_incoming_queue);
567 367 // |immediate_work_queue| is now empty so updates are no longer required.
568 // |any_thread().immediate_incoming_queue| is now empty so 368 return false;
569 // TimeDomain::UpdateQueues no longer needs to consider this queue for
570 // reloading.
571 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
572 } 369 }
573 370
574 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { 371 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
575 bool is_tracing; 372 bool is_tracing;
576 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, 373 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
577 &is_tracing); 374 &is_tracing);
578 if (!is_tracing) 375 if (!is_tracing)
579 return; 376 return;
580 377
581 // It's only safe to access the work queues from the main thread. 378 // It's only safe to access the work queues from the main thread.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 state->SetInteger("immediate_incoming_queue_size", 440 state->SetInteger("immediate_incoming_queue_size",
644 any_thread().immediate_incoming_queue.size()); 441 any_thread().immediate_incoming_queue.size());
645 state->SetInteger("delayed_incoming_queue_size", 442 state->SetInteger("delayed_incoming_queue_size",
646 main_thread_only().delayed_incoming_queue.size()); 443 main_thread_only().delayed_incoming_queue.size());
647 state->SetInteger("immediate_work_queue_size", 444 state->SetInteger("immediate_work_queue_size",
648 main_thread_only().immediate_work_queue->Size()); 445 main_thread_only().immediate_work_queue->Size());
649 state->SetInteger("delayed_work_queue_size", 446 state->SetInteger("delayed_work_queue_size",
650 main_thread_only().delayed_work_queue->Size()); 447 main_thread_only().delayed_work_queue->Size());
651 if (!main_thread_only().delayed_incoming_queue.empty()) { 448 if (!main_thread_only().delayed_incoming_queue.empty()) {
652 base::TimeDelta delay_to_next_task = 449 base::TimeDelta delay_to_next_task =
653 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time - 450 (main_thread_only().delayed_incoming_queue.top().delayed_run_time -
654 main_thread_only().time_domain->CreateLazyNow().Now()); 451 main_thread_only().time_domain->CreateLazyNow().Now());
655 state->SetDouble("delay_to_next_task_ms", 452 state->SetDouble("delay_to_next_task_ms",
656 delay_to_next_task.InMillisecondsF()); 453 delay_to_next_task.InMillisecondsF());
657 } 454 }
658 if (verbose_tracing_enabled) { 455 if (verbose_tracing_enabled) {
659 state->BeginArray("immediate_incoming_queue"); 456 state->BeginArray("immediate_incoming_queue");
660 QueueAsValueInto(any_thread().immediate_incoming_queue, state); 457 QueueAsValueInto(any_thread().immediate_incoming_queue, state);
661 state->EndArray(); 458 state->EndArray();
662 state->BeginArray("delayed_work_queue"); 459 state->BeginArray("delayed_work_queue");
663 main_thread_only().delayed_work_queue->AsValueInto(state); 460 main_thread_only().delayed_work_queue->AsValueInto(state);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 // Tasks posted after this point will have a strictly higher enqueue order 543 // Tasks posted after this point will have a strictly higher enqueue order
747 // and will be blocked from running. 544 // and will be blocked from running.
748 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( 545 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence(
749 main_thread_only().current_fence); 546 main_thread_only().current_fence);
750 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( 547 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence(
751 main_thread_only().current_fence); 548 main_thread_only().current_fence);
752 549
753 if (!task_unblocked && previous_fence) { 550 if (!task_unblocked && previous_fence) {
754 base::AutoLock lock(any_thread_lock_); 551 base::AutoLock lock(any_thread_lock_);
755 if (!any_thread().immediate_incoming_queue.empty() && 552 if (!any_thread().immediate_incoming_queue.empty() &&
756 any_thread().immediate_incoming_queue.begin()->enqueue_order() > 553 any_thread().immediate_incoming_queue.front().enqueue_order() >
757 previous_fence && 554 previous_fence &&
758 any_thread().immediate_incoming_queue.begin()->enqueue_order() < 555 any_thread().immediate_incoming_queue.front().enqueue_order() <
759 main_thread_only().current_fence) { 556 main_thread_only().current_fence) {
760 task_unblocked = true; 557 task_unblocked = true;
761 } 558 }
762 } 559 }
763 560
764 if (main_thread_only().is_enabled && task_unblocked) { 561 if (main_thread_only().is_enabled && task_unblocked) {
765 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 562 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
766 FROM_HERE); 563 FROM_HERE);
767 } 564 }
768 } 565 }
769 566
770 void TaskQueueImpl::RemoveFence() { 567 void TaskQueueImpl::RemoveFence() {
771 if (!main_thread_only().task_queue_manager) 568 if (!main_thread_only().task_queue_manager)
772 return; 569 return;
773 570
774 EnqueueOrder previous_fence = main_thread_only().current_fence; 571 EnqueueOrder previous_fence = main_thread_only().current_fence;
775 main_thread_only().current_fence = 0; 572 main_thread_only().current_fence = 0;
776 573
777 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); 574 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence();
778 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); 575 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence();
779 576
780 if (!task_unblocked && previous_fence) { 577 if (!task_unblocked && previous_fence) {
781 base::AutoLock lock(any_thread_lock_); 578 base::AutoLock lock(any_thread_lock_);
782 if (!any_thread().immediate_incoming_queue.empty() && 579 if (!any_thread().immediate_incoming_queue.empty() &&
783 any_thread().immediate_incoming_queue.begin()->enqueue_order() > 580 any_thread().immediate_incoming_queue.front().enqueue_order() >
784 previous_fence) { 581 previous_fence) {
785 task_unblocked = true; 582 task_unblocked = true;
786 } 583 }
787 } 584 }
788 585
789 if (main_thread_only().is_enabled && task_unblocked) { 586 if (main_thread_only().is_enabled && task_unblocked) {
790 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 587 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
791 FROM_HERE); 588 FROM_HERE);
792 } 589 }
793 } 590 }
794 591
795 bool TaskQueueImpl::BlockedByFence() const { 592 bool TaskQueueImpl::BlockedByFence() const {
796 if (!main_thread_only().current_fence) 593 if (!main_thread_only().current_fence)
797 return false; 594 return false;
798 595
799 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 596 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
800 !main_thread_only().delayed_work_queue->BlockedByFence()) { 597 !main_thread_only().delayed_work_queue->BlockedByFence()) {
801 return false; 598 return false;
802 } 599 }
803 600
804 base::AutoLock lock(any_thread_lock_); 601 base::AutoLock lock(any_thread_lock_);
805 if (any_thread().immediate_incoming_queue.empty()) 602 if (any_thread().immediate_incoming_queue.empty())
806 return true; 603 return true;
807 604
808 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > 605 return any_thread().immediate_incoming_queue.front().enqueue_order() >
809 main_thread_only().current_fence; 606 main_thread_only().current_fence;
810 } 607 }
811 608
812 bool TaskQueueImpl::BlockedByFenceLocked() const { 609 bool TaskQueueImpl::BlockedByFenceLocked() const {
813 if (!main_thread_only().current_fence) 610 if (!main_thread_only().current_fence)
814 return false; 611 return false;
815 612
816 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 613 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
817 !main_thread_only().delayed_work_queue->BlockedByFence()) { 614 !main_thread_only().delayed_work_queue->BlockedByFence()) {
818 return false; 615 return false;
819 } 616 }
820 617
821 if (any_thread().immediate_incoming_queue.empty()) 618 if (any_thread().immediate_incoming_queue.empty())
822 return true; 619 return true;
823 620
824 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > 621 return any_thread().immediate_incoming_queue.front().enqueue_order() >
825 main_thread_only().current_fence; 622 main_thread_only().current_fence;
826 } 623 }
827 624
828 // static 625 // static
829 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, 626 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue,
830 base::trace_event::TracedValue* state) { 627 base::trace_event::TracedValue* state) {
831 for (const Task& task : queue) { 628 // Remove const to search |queue| in the destructive manner. Restore the
832 TaskAsValueInto(task, state); 629 // content from |visited| later.
630 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue);
631 std::queue<Task> visited;
632 while (!mutable_queue->empty()) {
633 TaskAsValueInto(mutable_queue->front(), state);
634 visited.push(std::move(mutable_queue->front()));
635 mutable_queue->pop();
833 } 636 }
637 *mutable_queue = std::move(visited);
834 } 638 }
835 639
836 // static 640 // static
837 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, 641 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue,
838 base::trace_event::TracedValue* state) { 642 base::trace_event::TracedValue* state) {
839 for (const Task& task : queue) { 643 // Remove const to search |queue| in the destructive manner. Restore the
840 TaskAsValueInto(task, state); 644 // content from |visited| later.
645 std::priority_queue<Task>* mutable_queue =
646 const_cast<std::priority_queue<Task>*>(&queue);
647 std::priority_queue<Task> visited;
648 while (!mutable_queue->empty()) {
649 TaskAsValueInto(mutable_queue->top(), state);
650 visited.push(std::move(const_cast<Task&>(mutable_queue->top())));
651 mutable_queue->pop();
841 } 652 }
653 *mutable_queue = std::move(visited);
842 } 654 }
843 655
844 // static 656 // static
845 void TaskQueueImpl::TaskAsValueInto(const Task& task, 657 void TaskQueueImpl::TaskAsValueInto(const Task& task,
846 base::trace_event::TracedValue* state) { 658 base::trace_event::TracedValue* state) {
847 state->BeginDictionary(); 659 state->BeginDictionary();
848 state->SetString("posted_from", task.posted_from.ToString()); 660 state->SetString("posted_from", task.posted_from.ToString());
849 #ifndef NDEBUG 661 #ifndef NDEBUG
850 if (task.enqueue_order_set()) 662 if (task.enqueue_order_set())
851 state->SetInteger("enqueue_order", task.enqueue_order()); 663 state->SetInteger("enqueue_order", task.enqueue_order());
852 #else 664 #else
853 state->SetInteger("enqueue_order", task.enqueue_order()); 665 state->SetInteger("enqueue_order", task.enqueue_order());
854 #endif 666 #endif
855 state->SetInteger("sequence_num", task.sequence_num); 667 state->SetInteger("sequence_num", task.sequence_num);
856 state->SetBoolean("nestable", task.nestable); 668 state->SetBoolean("nestable", task.nestable);
857 state->SetBoolean("is_high_res", task.is_high_res); 669 state->SetBoolean("is_high_res", task.is_high_res);
670 state->SetBoolean("is_cancelled", task.task.IsCancelled());
858 state->SetDouble( 671 state->SetDouble(
859 "delayed_run_time", 672 "delayed_run_time",
860 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 673 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
861 state->EndDictionary(); 674 state->EndDictionary();
862 } 675 }
863 676
864 } // namespace internal 677 } // namespace internal
865 } // namespace scheduler 678 } // namespace scheduler
866 } // namespace blink 679 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698