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

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: Add missing file 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 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 task_type != TaskType::NON_NESTABLE)); 208 task_type != TaskType::NON_NESTABLE));
413 } 209 }
414 return true; 210 return true;
415 } 211 }
416 212
417 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread( 213 void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
418 Task pending_task, 214 Task pending_task,
419 base::TimeTicks now) { 215 base::TimeTicks now) {
420 main_thread_only().task_queue_manager->DidQueueTask(pending_task); 216 main_thread_only().task_queue_manager->DidQueueTask(pending_task);
421 217
422 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue. 218 // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue..
Sami 2016/09/08 16:35:02 nit: extra '.'?
alex clarke (OOO till 29th) 2016/09/08 16:43:28 Done.
423 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 219 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
424 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); 220 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
425 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, 221 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time,
426 now); 222 now);
427 TraceQueueSize(false); 223 TraceQueueSize(false);
428 } 224 }
429 225
430 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { 226 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
431 any_thread().task_queue_manager->DidQueueTask(pending_task); 227 any_thread().task_queue_manager->DidQueueTask(pending_task);
432 228
433 int thread_hop_task_sequence_number = 229 int thread_hop_task_sequence_number =
434 any_thread().task_queue_manager->GetNextSequenceNumber(); 230 any_thread().task_queue_manager->GetNextSequenceNumber();
(...skipping 13 matching lines...) Expand all
448 // There's no point posting a DoWork for a disabled queue, however we can 244 // 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. 245 // only tell if it's disabled from the main thread.
450 if (base::PlatformThread::CurrentId() == thread_id_) { 246 if (base::PlatformThread::CurrentId() == thread_id_) {
451 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) 247 if (main_thread_only().is_enabled && !BlockedByFenceLocked())
452 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 248 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
453 } else { 249 } else {
454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); 250 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
455 } 251 }
456 } 252 }
457 any_thread().task_queue_manager->DidQueueTask(pending_task); 253 any_thread().task_queue_manager->DidQueueTask(pending_task);
458 // We expect |pending_task| to be inserted at the end. Amoritized O(1). 254 any_thread().immediate_incoming_queue.push(std::move(pending_task));
459 any_thread().immediate_incoming_queue.insert(
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); 255 TraceQueueSize(true);
465 } 256 }
466 257
467 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) { 258 void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
468 DCHECK(main_thread_checker_.CalledOnValidThread()); 259 DCHECK(main_thread_checker_.CalledOnValidThread());
469 base::TimeTicks delayed_run_time = pending_task.delayed_run_time; 260 base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
470 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); 261 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
471 // Make sure |delayed_run_time| isn't in the past. 262 // Make sure |delayed_run_time| isn't in the past.
472 if (delayed_run_time < time_domain_now) { 263 if (delayed_run_time < time_domain_now) {
473 delayed_run_time = time_domain_now; 264 delayed_run_time = time_domain_now;
474 pending_task.delayed_run_time = time_domain_now; 265 pending_task.delayed_run_time = time_domain_now;
475 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); 266 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
476 LazyNow lazy_now(time_domain_now); 267 LazyNow lazy_now(time_domain_now);
477 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); 268 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now);
478 } else { 269 } else {
479 main_thread_only().delayed_incoming_queue.insert(std::move(pending_task)); 270 main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
480 main_thread_only().time_domain->ScheduleDelayedWork( 271 main_thread_only().time_domain->ScheduleDelayedWork(
481 this, delayed_run_time, main_thread_only().time_domain->Now()); 272 this, delayed_run_time, main_thread_only().time_domain->Now());
482 } 273 }
483 TraceQueueSize(false); 274 TraceQueueSize(false);
484 } 275 }
485 276
486 void TaskQueueImpl::SetQueueEnabled(bool enabled) { 277 void TaskQueueImpl::SetQueueEnabled(bool enabled) {
487 if (main_thread_only().is_enabled == enabled) 278 if (main_thread_only().is_enabled == enabled)
488 return; 279 return;
489 main_thread_only().is_enabled = enabled; 280 main_thread_only().is_enabled = enabled;
490 if (!main_thread_only().task_queue_manager) 281 if (!main_thread_only().task_queue_manager)
491 return; 282 return;
492 if (enabled) { 283 if (enabled) {
493 // Note it's the job of the selector to tell the TaskQueueManager if 284 // Note it's the job of the selector to tell the TaskQueueManager if
494 // a DoWork needs posting. 285 // a DoWork needs posting.
495 main_thread_only().task_queue_manager->selector_.EnableQueue(this); 286 main_thread_only().task_queue_manager->selector_.EnableQueue(this);
496 } else { 287 } else {
497 main_thread_only().task_queue_manager->selector_.DisableQueue(this); 288 main_thread_only().task_queue_manager->selector_.DisableQueue(this);
498 } 289 }
499 } 290 }
500 291
501 bool TaskQueueImpl::IsQueueEnabled() const { 292 bool TaskQueueImpl::IsQueueEnabled() const {
502 return main_thread_only().is_enabled; 293 return main_thread_only().is_enabled;
503 } 294 }
504 295
505 bool TaskQueueImpl::IsEmpty() const { 296 bool TaskQueueImpl::IsEmpty() const {
506 if (!main_thread_only().delayed_work_queue->Empty() || 297 if (!main_thread_only().delayed_work_queue->Empty() ||
298 !main_thread_only().delayed_incoming_queue.empty() ||
507 !main_thread_only().immediate_work_queue->Empty()) { 299 !main_thread_only().immediate_work_queue->Empty()) {
508 return false; 300 return false;
509 } 301 }
510 302
511 base::AutoLock lock(any_thread_lock_); 303 base::AutoLock lock(any_thread_lock_);
512 return any_thread().immediate_incoming_queue.empty() && 304 return any_thread().immediate_incoming_queue.empty();
513 main_thread_only().delayed_incoming_queue.empty();
514 } 305 }
515 306
516 bool TaskQueueImpl::HasPendingImmediateWork() const { 307 bool TaskQueueImpl::HasPendingImmediateWork() const {
517 // Any work queue tasks count as immediate work. 308 // Any work queue tasks count as immediate work.
518 if (!main_thread_only().delayed_work_queue->Empty() || 309 if (!main_thread_only().delayed_work_queue->Empty() ||
519 !main_thread_only().immediate_work_queue->Empty()) { 310 !main_thread_only().immediate_work_queue->Empty()) {
520 return true; 311 return true;
521 } 312 }
522 313
523 // Tasks on |delayed_incoming_queue| that could run now, count as 314 // Tasks on |delayed_incoming_queue| that could run now, count as
524 // immediate work. 315 // immediate work.
525 if (!main_thread_only().delayed_incoming_queue.empty() && 316 if (!main_thread_only().delayed_incoming_queue.empty() &&
526 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= 317 main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
527 main_thread_only().time_domain->CreateLazyNow().Now()) { 318 main_thread_only().time_domain->CreateLazyNow().Now()) {
528 return true; 319 return true;
529 } 320 }
530 321
531 // Finally tasks on |immediate_incoming_queue| count as immediate work. 322 // Finally tasks on |immediate_incoming_queue| count as immediate work.
532 base::AutoLock lock(any_thread_lock_); 323 base::AutoLock lock(any_thread_lock_);
533 return !any_thread().immediate_incoming_queue.empty(); 324 return !any_thread().immediate_incoming_queue.empty();
534 } 325 }
535 326
536 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { 327 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) {
537 // Enqueue all delayed tasks that should be running now. 328 // Enqueue all delayed tasks that should be running now.
538 while (!main_thread_only().delayed_incoming_queue.empty()) { 329 while (!main_thread_only().delayed_incoming_queue.empty()) {
539 DelayedRunTimeQueue::iterator next_task = 330 // TODO(alexclarke): Use extract() when C++17 is allowed.
540 main_thread_only().delayed_incoming_queue.begin(); 331 Task& task =
541 if (next_task->delayed_run_time > lazy_now->Now()) 332 const_cast<Task&>(main_thread_only().delayed_incoming_queue.top());
333 if (task.task.IsCancelled()) {
334 main_thread_only().delayed_incoming_queue.pop();
335 continue;
336 }
337 if (task.delayed_run_time > lazy_now->Now())
542 break; 338 break;
543 // TODO(alexclarke): Use extract() when C++17 is allowed.
544 Task& task = const_cast<Task&>(*next_task);
545 task.set_enqueue_order( 339 task.set_enqueue_order(
546 main_thread_only().task_queue_manager->GetNextSequenceNumber()); 340 main_thread_only().task_queue_manager->GetNextSequenceNumber());
547 main_thread_only().delayed_work_queue->Push(std::move(task)); 341 main_thread_only().delayed_work_queue->Push(std::move(task));
548 main_thread_only().delayed_incoming_queue.erase(next_task); 342 main_thread_only().delayed_incoming_queue.pop();
549 } 343 }
550 } 344 }
551 345
552 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { 346 bool TaskQueueImpl::MaybeUpdateImmediateWorkQueues() {
553 if (!main_thread_only().task_queue_manager) 347 if (!main_thread_only().task_queue_manager)
554 return; 348 return false;
555 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
556 TraceQueueSize(false);
557 }
558 349
559 void TaskQueueImpl::UpdateImmediateWorkQueue() { 350 if (!main_thread_only().immediate_work_queue->Empty())
560 DCHECK(main_thread_only().immediate_work_queue->Empty()); 351 return true;
352
561 base::AutoLock lock(any_thread_lock_); 353 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( 354 main_thread_only().immediate_work_queue->SwapLocked(
566 any_thread().immediate_incoming_queue); 355 any_thread().immediate_incoming_queue);
567 356 // |immediate_work_queue| is now empty so updates are no longer required.
568 // |any_thread().immediate_incoming_queue| is now empty so 357 return false;
569 // TimeDomain::UpdateQueues no longer needs to consider this queue for
570 // reloading.
571 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
572 } 358 }
573 359
574 void TaskQueueImpl::TraceQueueSize(bool is_locked) const { 360 void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
575 bool is_tracing; 361 bool is_tracing;
576 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_, 362 TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
577 &is_tracing); 363 &is_tracing);
578 if (!is_tracing) 364 if (!is_tracing)
579 return; 365 return;
580 366
581 // It's only safe to access the work queues from the main thread. 367 // 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", 429 state->SetInteger("immediate_incoming_queue_size",
644 any_thread().immediate_incoming_queue.size()); 430 any_thread().immediate_incoming_queue.size());
645 state->SetInteger("delayed_incoming_queue_size", 431 state->SetInteger("delayed_incoming_queue_size",
646 main_thread_only().delayed_incoming_queue.size()); 432 main_thread_only().delayed_incoming_queue.size());
647 state->SetInteger("immediate_work_queue_size", 433 state->SetInteger("immediate_work_queue_size",
648 main_thread_only().immediate_work_queue->Size()); 434 main_thread_only().immediate_work_queue->Size());
649 state->SetInteger("delayed_work_queue_size", 435 state->SetInteger("delayed_work_queue_size",
650 main_thread_only().delayed_work_queue->Size()); 436 main_thread_only().delayed_work_queue->Size());
651 if (!main_thread_only().delayed_incoming_queue.empty()) { 437 if (!main_thread_only().delayed_incoming_queue.empty()) {
652 base::TimeDelta delay_to_next_task = 438 base::TimeDelta delay_to_next_task =
653 (main_thread_only().delayed_incoming_queue.begin()->delayed_run_time - 439 (main_thread_only().delayed_incoming_queue.top().delayed_run_time -
654 main_thread_only().time_domain->CreateLazyNow().Now()); 440 main_thread_only().time_domain->CreateLazyNow().Now());
655 state->SetDouble("delay_to_next_task_ms", 441 state->SetDouble("delay_to_next_task_ms",
656 delay_to_next_task.InMillisecondsF()); 442 delay_to_next_task.InMillisecondsF());
657 } 443 }
658 if (verbose_tracing_enabled) { 444 if (verbose_tracing_enabled) {
659 state->BeginArray("immediate_incoming_queue"); 445 state->BeginArray("immediate_incoming_queue");
660 QueueAsValueInto(any_thread().immediate_incoming_queue, state); 446 QueueAsValueInto(any_thread().immediate_incoming_queue, state);
661 state->EndArray(); 447 state->EndArray();
662 state->BeginArray("delayed_work_queue"); 448 state->BeginArray("delayed_work_queue");
663 main_thread_only().delayed_work_queue->AsValueInto(state); 449 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 532 // Tasks posted after this point will have a strictly higher enqueue order
747 // and will be blocked from running. 533 // and will be blocked from running.
748 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( 534 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence(
749 main_thread_only().current_fence); 535 main_thread_only().current_fence);
750 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( 536 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence(
751 main_thread_only().current_fence); 537 main_thread_only().current_fence);
752 538
753 if (!task_unblocked && previous_fence) { 539 if (!task_unblocked && previous_fence) {
754 base::AutoLock lock(any_thread_lock_); 540 base::AutoLock lock(any_thread_lock_);
755 if (!any_thread().immediate_incoming_queue.empty() && 541 if (!any_thread().immediate_incoming_queue.empty() &&
756 any_thread().immediate_incoming_queue.begin()->enqueue_order() > 542 any_thread().immediate_incoming_queue.front().enqueue_order() >
757 previous_fence && 543 previous_fence &&
758 any_thread().immediate_incoming_queue.begin()->enqueue_order() < 544 any_thread().immediate_incoming_queue.front().enqueue_order() <
759 main_thread_only().current_fence) { 545 main_thread_only().current_fence) {
760 task_unblocked = true; 546 task_unblocked = true;
761 } 547 }
762 } 548 }
763 549
764 if (main_thread_only().is_enabled && task_unblocked) { 550 if (main_thread_only().is_enabled && task_unblocked) {
765 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 551 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
766 FROM_HERE); 552 FROM_HERE);
767 } 553 }
768 } 554 }
769 555
770 void TaskQueueImpl::RemoveFence() { 556 void TaskQueueImpl::RemoveFence() {
771 if (!main_thread_only().task_queue_manager) 557 if (!main_thread_only().task_queue_manager)
772 return; 558 return;
773 559
774 EnqueueOrder previous_fence = main_thread_only().current_fence; 560 EnqueueOrder previous_fence = main_thread_only().current_fence;
775 main_thread_only().current_fence = 0; 561 main_thread_only().current_fence = 0;
776 562
777 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); 563 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence();
778 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); 564 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence();
779 565
780 if (!task_unblocked && previous_fence) { 566 if (!task_unblocked && previous_fence) {
781 base::AutoLock lock(any_thread_lock_); 567 base::AutoLock lock(any_thread_lock_);
782 if (!any_thread().immediate_incoming_queue.empty() && 568 if (!any_thread().immediate_incoming_queue.empty() &&
783 any_thread().immediate_incoming_queue.begin()->enqueue_order() > 569 any_thread().immediate_incoming_queue.front().enqueue_order() >
784 previous_fence) { 570 previous_fence) {
785 task_unblocked = true; 571 task_unblocked = true;
786 } 572 }
787 } 573 }
788 574
789 if (main_thread_only().is_enabled && task_unblocked) { 575 if (main_thread_only().is_enabled && task_unblocked) {
790 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( 576 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
791 FROM_HERE); 577 FROM_HERE);
792 } 578 }
793 } 579 }
794 580
795 bool TaskQueueImpl::BlockedByFence() const { 581 bool TaskQueueImpl::BlockedByFence() const {
796 if (!main_thread_only().current_fence) 582 if (!main_thread_only().current_fence)
797 return false; 583 return false;
798 584
799 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 585 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
800 !main_thread_only().delayed_work_queue->BlockedByFence()) { 586 !main_thread_only().delayed_work_queue->BlockedByFence()) {
801 return false; 587 return false;
802 } 588 }
803 589
804 base::AutoLock lock(any_thread_lock_); 590 base::AutoLock lock(any_thread_lock_);
805 if (any_thread().immediate_incoming_queue.empty()) 591 if (any_thread().immediate_incoming_queue.empty())
806 return true; 592 return true;
807 593
808 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > 594 return any_thread().immediate_incoming_queue.front().enqueue_order() >
809 main_thread_only().current_fence; 595 main_thread_only().current_fence;
810 } 596 }
811 597
812 bool TaskQueueImpl::BlockedByFenceLocked() const { 598 bool TaskQueueImpl::BlockedByFenceLocked() const {
813 if (!main_thread_only().current_fence) 599 if (!main_thread_only().current_fence)
814 return false; 600 return false;
815 601
816 if (!main_thread_only().immediate_work_queue->BlockedByFence() || 602 if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
817 !main_thread_only().delayed_work_queue->BlockedByFence()) { 603 !main_thread_only().delayed_work_queue->BlockedByFence()) {
818 return false; 604 return false;
819 } 605 }
820 606
821 if (any_thread().immediate_incoming_queue.empty()) 607 if (any_thread().immediate_incoming_queue.empty())
822 return true; 608 return true;
823 609
824 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > 610 return any_thread().immediate_incoming_queue.front().enqueue_order() >
825 main_thread_only().current_fence; 611 main_thread_only().current_fence;
826 } 612 }
827 613
828 // static 614 // static
829 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, 615 void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue,
830 base::trace_event::TracedValue* state) { 616 base::trace_event::TracedValue* state) {
831 for (const Task& task : queue) { 617 // Remove const to search |queue| in the destructive manner. Restore the
832 TaskAsValueInto(task, state); 618 // content from |visited| later.
619 std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue);
620 std::queue<Task> visited;
621 while (!mutable_queue->empty()) {
622 TaskAsValueInto(mutable_queue->front(), state);
623 visited.push(std::move(mutable_queue->front()));
624 mutable_queue->pop();
833 } 625 }
626 *mutable_queue = std::move(visited);
834 } 627 }
835 628
836 // static 629 // static
837 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, 630 void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue,
838 base::trace_event::TracedValue* state) { 631 base::trace_event::TracedValue* state) {
839 for (const Task& task : queue) { 632 // Remove const to search |queue| in the destructive manner. Restore the
840 TaskAsValueInto(task, state); 633 // content from |visited| later.
634 std::priority_queue<Task>* mutable_queue =
635 const_cast<std::priority_queue<Task>*>(&queue);
636 std::priority_queue<Task> visited;
637 while (!mutable_queue->empty()) {
638 TaskAsValueInto(mutable_queue->top(), state);
639 visited.push(std::move(const_cast<Task&>(mutable_queue->top())));
640 mutable_queue->pop();
841 } 641 }
642 *mutable_queue = std::move(visited);
842 } 643 }
843 644
844 // static 645 // static
845 void TaskQueueImpl::TaskAsValueInto(const Task& task, 646 void TaskQueueImpl::TaskAsValueInto(const Task& task,
846 base::trace_event::TracedValue* state) { 647 base::trace_event::TracedValue* state) {
847 state->BeginDictionary(); 648 state->BeginDictionary();
848 state->SetString("posted_from", task.posted_from.ToString()); 649 state->SetString("posted_from", task.posted_from.ToString());
849 #ifndef NDEBUG 650 #ifndef NDEBUG
850 if (task.enqueue_order_set()) 651 if (task.enqueue_order_set())
851 state->SetInteger("enqueue_order", task.enqueue_order()); 652 state->SetInteger("enqueue_order", task.enqueue_order());
852 #else 653 #else
853 state->SetInteger("enqueue_order", task.enqueue_order()); 654 state->SetInteger("enqueue_order", task.enqueue_order());
854 #endif 655 #endif
855 state->SetInteger("sequence_num", task.sequence_num); 656 state->SetInteger("sequence_num", task.sequence_num);
856 state->SetBoolean("nestable", task.nestable); 657 state->SetBoolean("nestable", task.nestable);
857 state->SetBoolean("is_high_res", task.is_high_res); 658 state->SetBoolean("is_high_res", task.is_high_res);
659 state->SetBoolean("is_cancelled", task.task.IsCancelled());
858 state->SetDouble( 660 state->SetDouble(
859 "delayed_run_time", 661 "delayed_run_time",
860 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); 662 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
861 state->EndDictionary(); 663 state->EndDictionary();
862 } 664 }
863 665
864 } // namespace internal 666 } // namespace internal
865 } // namespace scheduler 667 } // namespace scheduler
866 } // namespace blink 668 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698