OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "platform/scheduler/base/task_queue_impl.h" | 5 #include "platform/scheduler/base/task_queue_impl.h" |
6 | 6 |
7 #include "base/trace_event/blame_context.h" | 7 #include "base/trace_event/blame_context.h" |
8 #include "platform/scheduler/base/task_queue_manager.h" | 8 #include "platform/scheduler/base/task_queue_manager.h" |
9 #include "platform/scheduler/base/task_queue_manager_delegate.h" | 9 #include "platform/scheduler/base/task_queue_manager_delegate.h" |
10 #include "platform/scheduler/base/time_domain.h" | 10 #include "platform/scheduler/base/time_domain.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 | 43 |
44 namespace internal { | 44 namespace internal { |
45 | 45 |
46 TaskQueueImpl::TaskQueueImpl( | 46 TaskQueueImpl::TaskQueueImpl( |
47 TaskQueueManager* task_queue_manager, | 47 TaskQueueManager* task_queue_manager, |
48 TimeDomain* time_domain, | 48 TimeDomain* time_domain, |
49 const Spec& spec, | 49 const Spec& spec, |
50 const char* disabled_by_default_tracing_category, | 50 const char* disabled_by_default_tracing_category, |
51 const char* disabled_by_default_verbose_tracing_category) | 51 const char* disabled_by_default_verbose_tracing_category) |
52 : thread_id_(base::PlatformThread::CurrentId()), | 52 : thread_id_(base::PlatformThread::CurrentId()), |
53 any_thread_(task_queue_manager, spec.pump_policy, time_domain), | 53 any_thread_(task_queue_manager, time_domain), |
54 name_(spec.name), | 54 name_(spec.name), |
55 disabled_by_default_tracing_category_( | 55 disabled_by_default_tracing_category_( |
56 disabled_by_default_tracing_category), | 56 disabled_by_default_tracing_category), |
57 disabled_by_default_verbose_tracing_category_( | 57 disabled_by_default_verbose_tracing_category_( |
58 disabled_by_default_verbose_tracing_category), | 58 disabled_by_default_verbose_tracing_category), |
59 main_thread_only_(task_queue_manager, | 59 main_thread_only_(task_queue_manager, this, time_domain), |
60 spec.pump_policy, | |
61 this, | |
62 time_domain), | |
63 wakeup_policy_(spec.wakeup_policy), | |
64 should_monitor_quiescence_(spec.should_monitor_quiescence), | 60 should_monitor_quiescence_(spec.should_monitor_quiescence), |
65 should_notify_observers_(spec.should_notify_observers), | 61 should_notify_observers_(spec.should_notify_observers), |
66 should_report_when_execution_blocked_( | 62 should_report_when_execution_blocked_( |
67 spec.should_report_when_execution_blocked) { | 63 spec.should_report_when_execution_blocked) { |
68 DCHECK(time_domain); | 64 DCHECK(time_domain); |
69 time_domain->RegisterQueue(this); | 65 time_domain->RegisterQueue(this); |
70 } | 66 } |
71 | 67 |
72 TaskQueueImpl::~TaskQueueImpl() { | 68 TaskQueueImpl::~TaskQueueImpl() { |
73 #if DCHECK_IS_ON() | 69 #if DCHECK_IS_ON() |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 | 160 |
165 if (a.delayed_run_time > b.delayed_run_time) | 161 if (a.delayed_run_time > b.delayed_run_time) |
166 return false; | 162 return false; |
167 | 163 |
168 // If the times happen to match, then we use the sequence number to decide. | 164 // If the times happen to match, then we use the sequence number to decide. |
169 // Compare the difference to support integer roll-over. | 165 // Compare the difference to support integer roll-over. |
170 return (a.sequence_num - b.sequence_num) < 0; | 166 return (a.sequence_num - b.sequence_num) < 0; |
171 } | 167 } |
172 | 168 |
173 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, | 169 TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager, |
174 PumpPolicy pump_policy, | |
175 TimeDomain* time_domain) | 170 TimeDomain* time_domain) |
176 : task_queue_manager(task_queue_manager), | 171 : task_queue_manager(task_queue_manager), |
177 pump_policy(pump_policy), | |
178 time_domain(time_domain), | 172 time_domain(time_domain), |
179 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { | 173 immediate_incoming_queue(&TaskQueueImpl::Task::EnqueueOrderComparatorFn) { |
180 } | 174 } |
181 | 175 |
182 TaskQueueImpl::AnyThread::~AnyThread() {} | 176 TaskQueueImpl::AnyThread::~AnyThread() {} |
183 | 177 |
184 TaskQueueImpl::MainThreadOnly::MainThreadOnly( | 178 TaskQueueImpl::MainThreadOnly::MainThreadOnly( |
185 TaskQueueManager* task_queue_manager, | 179 TaskQueueManager* task_queue_manager, |
186 PumpPolicy pump_policy, | |
187 TaskQueueImpl* task_queue, | 180 TaskQueueImpl* task_queue, |
188 TimeDomain* time_domain) | 181 TimeDomain* time_domain) |
189 : task_queue_manager(task_queue_manager), | 182 : task_queue_manager(task_queue_manager), |
190 pump_policy(pump_policy), | |
191 time_domain(time_domain), | 183 time_domain(time_domain), |
192 delayed_work_queue( | 184 delayed_work_queue( |
193 new WorkQueue(task_queue, | 185 new WorkQueue(task_queue, |
194 "delayed", | 186 "delayed", |
195 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), | 187 &TaskQueueImpl::Task::DelayedRunTimeComparatorFn)), |
196 immediate_work_queue( | 188 immediate_work_queue( |
197 new WorkQueue(task_queue, | 189 new WorkQueue(task_queue, |
198 "immediate", | 190 "immediate", |
199 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), | 191 &TaskQueueImpl::Task::EnqueueOrderComparatorFn)), |
200 set_index(0), | 192 set_index(0), |
(...skipping 30 matching lines...) Expand all Loading... |
231 const base::Closure& task, | 223 const base::Closure& task, |
232 base::TimeDelta delay) { | 224 base::TimeDelta delay) { |
233 if (!main_thread_only().task_queue_manager) | 225 if (!main_thread_only().task_queue_manager) |
234 return TaskHandle(); | 226 return TaskHandle(); |
235 | 227 |
236 EnqueueOrder sequence_number = | 228 EnqueueOrder sequence_number = |
237 main_thread_only().task_queue_manager->GetNextSequenceNumber(); | 229 main_thread_only().task_queue_manager->GetNextSequenceNumber(); |
238 | 230 |
239 if (delay.is_zero()) { | 231 if (delay.is_zero()) { |
240 base::AutoLock lock(any_thread_lock_); | 232 base::AutoLock lock(any_thread_lock_); |
| 233 // If the |immediate_incoming_queue| is empty and the queue is enabled then |
| 234 // we need a DoWork posted to make it run. |
| 235 if (any_thread().immediate_incoming_queue.empty() && |
| 236 main_thread_only().is_enabled && !BlockedByFence()) { |
| 237 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 238 } |
241 PushOntoImmediateIncomingQueueLocked( | 239 PushOntoImmediateIncomingQueueLocked( |
242 Task(from_here, task, base::TimeTicks(), sequence_number, true, | 240 Task(from_here, task, base::TimeTicks(), sequence_number, true, |
243 sequence_number)); | 241 sequence_number)); |
244 | 242 |
245 return TaskHandle(this, sequence_number); | 243 return TaskHandle(this, sequence_number); |
246 } else { | 244 } else { |
247 DCHECK_GT(delay, base::TimeDelta()); | 245 DCHECK_GT(delay, base::TimeDelta()); |
248 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); | 246 base::TimeTicks time_domain_now = main_thread_only().time_domain->Now(); |
249 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; | 247 base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay; |
250 PushOntoDelayedIncomingQueueFromMainThread( | 248 PushOntoDelayedIncomingQueueFromMainThread( |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 const tracked_objects::Location& from_here, | 365 const tracked_objects::Location& from_here, |
368 const base::Closure& task, | 366 const base::Closure& task, |
369 TaskType task_type) { | 367 TaskType task_type) { |
370 base::AutoLock lock(any_thread_lock_); | 368 base::AutoLock lock(any_thread_lock_); |
371 if (!any_thread().task_queue_manager) | 369 if (!any_thread().task_queue_manager) |
372 return false; | 370 return false; |
373 | 371 |
374 EnqueueOrder sequence_number = | 372 EnqueueOrder sequence_number = |
375 any_thread().task_queue_manager->GetNextSequenceNumber(); | 373 any_thread().task_queue_manager->GetNextSequenceNumber(); |
376 | 374 |
| 375 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 376 // it run. |
| 377 if (any_thread().immediate_incoming_queue.empty()) { |
| 378 // There's no point posting a DoWork for a disabled queue, however we can |
| 379 // only tell if it's disabled from the main thread. |
| 380 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 381 if (main_thread_only().is_enabled && !BlockedByFence()) |
| 382 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 383 } else { |
| 384 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 385 } |
| 386 } |
| 387 |
377 PushOntoImmediateIncomingQueueLocked( | 388 PushOntoImmediateIncomingQueueLocked( |
378 Task(from_here, task, base::TimeTicks(), sequence_number, | 389 Task(from_here, task, base::TimeTicks(), sequence_number, |
379 task_type != TaskType::NON_NESTABLE, sequence_number)); | 390 task_type != TaskType::NON_NESTABLE, sequence_number)); |
380 return true; | 391 return true; |
381 } | 392 } |
382 | 393 |
383 bool TaskQueueImpl::PostDelayedTaskImpl( | 394 bool TaskQueueImpl::PostDelayedTaskImpl( |
384 const tracked_objects::Location& from_here, | 395 const tracked_objects::Location& from_here, |
385 const base::Closure& task, | 396 const base::Closure& task, |
386 base::TimeDelta delay, | 397 base::TimeDelta delay, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, | 443 main_thread_only().time_domain->ScheduleDelayedWork(this, delayed_run_time, |
433 now); | 444 now); |
434 TraceQueueSize(false); | 445 TraceQueueSize(false); |
435 } | 446 } |
436 | 447 |
437 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { | 448 void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) { |
438 any_thread().task_queue_manager->DidQueueTask(pending_task); | 449 any_thread().task_queue_manager->DidQueueTask(pending_task); |
439 | 450 |
440 int thread_hop_task_sequence_number = | 451 int thread_hop_task_sequence_number = |
441 any_thread().task_queue_manager->GetNextSequenceNumber(); | 452 any_thread().task_queue_manager->GetNextSequenceNumber(); |
| 453 |
| 454 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
| 455 // it run. |
| 456 if (any_thread().immediate_incoming_queue.empty()) |
| 457 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 458 |
442 PushOntoImmediateIncomingQueueLocked( | 459 PushOntoImmediateIncomingQueueLocked( |
443 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 460 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
444 base::Passed(&pending_task)), | 461 base::Passed(&pending_task)), |
445 base::TimeTicks(), thread_hop_task_sequence_number, false, | 462 base::TimeTicks(), thread_hop_task_sequence_number, false, |
446 thread_hop_task_sequence_number)); | 463 thread_hop_task_sequence_number)); |
447 } | 464 } |
448 | 465 |
449 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 466 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
450 if (any_thread().immediate_incoming_queue.empty()) | 467 if (any_thread().immediate_incoming_queue.empty()) |
451 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 468 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
452 if (any_thread().pump_policy == PumpPolicy::AUTO && | |
453 any_thread().immediate_incoming_queue.empty()) { | |
454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | |
455 } | |
456 any_thread().task_queue_manager->DidQueueTask(pending_task); | 469 any_thread().task_queue_manager->DidQueueTask(pending_task); |
457 // We expect |pending_task| to be inserted at the end. Amoritized O(1). | 470 // We expect |pending_task| to be inserted at the end. Amoritized O(1). |
458 any_thread().immediate_incoming_queue.insert( | 471 any_thread().immediate_incoming_queue.insert( |
459 any_thread().immediate_incoming_queue.end(), | 472 any_thread().immediate_incoming_queue.end(), |
460 std::move(pending_task)); | 473 std::move(pending_task)); |
461 DCHECK_EQ(pending_task.enqueue_order(), | 474 DCHECK_EQ(pending_task.enqueue_order(), |
462 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); | 475 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); |
463 TraceQueueSize(true); | 476 TraceQueueSize(true); |
464 } | 477 } |
465 | 478 |
(...skipping 16 matching lines...) Expand all Loading... |
482 TraceQueueSize(false); | 495 TraceQueueSize(false); |
483 } | 496 } |
484 | 497 |
485 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 498 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
486 if (main_thread_only().is_enabled == enabled) | 499 if (main_thread_only().is_enabled == enabled) |
487 return; | 500 return; |
488 main_thread_only().is_enabled = enabled; | 501 main_thread_only().is_enabled = enabled; |
489 if (!main_thread_only().task_queue_manager) | 502 if (!main_thread_only().task_queue_manager) |
490 return; | 503 return; |
491 if (enabled) { | 504 if (enabled) { |
| 505 // Note it's the job of the selector to tell the TaskQueueManager if |
| 506 // a DoWork needs posting. |
492 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 507 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
493 } else { | 508 } else { |
494 main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 509 main_thread_only().task_queue_manager->selector_.DisableQueue(this); |
495 } | 510 } |
496 } | 511 } |
497 | 512 |
498 bool TaskQueueImpl::IsQueueEnabled() const { | 513 bool TaskQueueImpl::IsQueueEnabled() const { |
499 return main_thread_only().is_enabled; | 514 return main_thread_only().is_enabled; |
500 } | 515 } |
501 | 516 |
502 bool TaskQueueImpl::IsEmpty() const { | 517 bool TaskQueueImpl::IsEmpty() const { |
503 if (!main_thread_only().delayed_work_queue->Empty() || | 518 if (!main_thread_only().delayed_work_queue->Empty() || |
504 !main_thread_only().immediate_work_queue->Empty()) { | 519 !main_thread_only().immediate_work_queue->Empty()) { |
505 return false; | 520 return false; |
506 } | 521 } |
507 | 522 |
508 base::AutoLock lock(any_thread_lock_); | 523 base::AutoLock lock(any_thread_lock_); |
509 return any_thread().immediate_incoming_queue.empty() && | 524 return any_thread().immediate_incoming_queue.empty() && |
510 main_thread_only().delayed_incoming_queue.empty(); | 525 main_thread_only().delayed_incoming_queue.empty(); |
511 } | 526 } |
512 | 527 |
513 bool TaskQueueImpl::HasPendingImmediateWork() const { | 528 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 529 // Any work queue tasks count as immediate work. |
514 if (!main_thread_only().delayed_work_queue->Empty() || | 530 if (!main_thread_only().delayed_work_queue->Empty() || |
515 !main_thread_only().immediate_work_queue->Empty()) { | 531 !main_thread_only().immediate_work_queue->Empty()) { |
516 return true; | 532 return true; |
517 } | 533 } |
518 | 534 |
519 return NeedsPumping(); | 535 // Tasks on |delayed_incoming_queue| that could run now, count as |
520 } | 536 // immediate work. |
521 | 537 if (!main_thread_only().delayed_incoming_queue.empty() && |
522 bool TaskQueueImpl::NeedsPumping() const { | 538 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
523 if (!main_thread_only().immediate_work_queue->Empty()) | 539 main_thread_only().time_domain->CreateLazyNow().Now()) { |
524 return false; | |
525 | |
526 base::AutoLock lock(any_thread_lock_); | |
527 if (!any_thread().immediate_incoming_queue.empty()) | |
528 return true; | |
529 | |
530 // If there's no immediate Incoming work then we only need pumping if there | |
531 // is a delayed task that should be running now. | |
532 if (main_thread_only().delayed_incoming_queue.empty()) | |
533 return false; | |
534 | |
535 return main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= | |
536 main_thread_only().time_domain->CreateLazyNow().Now(); | |
537 } | |
538 | |
539 bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked( | |
540 const Task* task) { | |
541 // A null task is passed when UpdateQueue is called before any task is run. | |
542 // In this case we don't want to pump an after_wakeup queue, so return true | |
543 // here. | |
544 if (!task) | |
545 return true; | |
546 | |
547 // Return false if task is newer than the oldest immediate task. | |
548 if (!any_thread().immediate_incoming_queue.empty() && | |
549 task->enqueue_order() > | |
550 any_thread().immediate_incoming_queue.begin()->enqueue_order()) { | |
551 return false; | |
552 } | |
553 return true; | |
554 } | |
555 | |
556 bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) { | |
557 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
558 // A null task is passed when UpdateQueue is called before any task is run. | |
559 // In this case we don't want to pump an after_wakeup queue, so return true | |
560 // here. | |
561 if (!task) | |
562 return true; | |
563 | |
564 EnqueueOrder enqueue_order; | |
565 if (!main_thread_only().delayed_work_queue->GetFrontTaskEnqueueOrder( | |
566 &enqueue_order)) { | |
567 return true; | 540 return true; |
568 } | 541 } |
569 | 542 |
570 return task->enqueue_order() < enqueue_order; | 543 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
571 } | 544 base::AutoLock lock(any_thread_lock_); |
572 | 545 return !any_thread().immediate_incoming_queue.empty(); |
573 bool TaskQueueImpl::ShouldAutoPumpImmediateQueueLocked( | |
574 bool should_trigger_wakeup, | |
575 const Task* previous_task) { | |
576 if (main_thread_only().pump_policy == PumpPolicy::MANUAL) | |
577 return false; | |
578 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | |
579 (!should_trigger_wakeup || | |
580 TaskIsOlderThanQueuedImmediateTasksLocked(previous_task))) | |
581 return false; | |
582 return true; | |
583 } | |
584 | |
585 bool TaskQueueImpl::ShouldAutoPumpDelayedQueue(bool should_trigger_wakeup, | |
586 const Task* previous_task) { | |
587 if (main_thread_only().pump_policy == PumpPolicy::MANUAL) | |
588 return false; | |
589 if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP && | |
590 (!should_trigger_wakeup || | |
591 TaskIsOlderThanQueuedDelayedTasks(previous_task))) | |
592 return false; | |
593 return true; | |
594 } | 546 } |
595 | 547 |
596 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 548 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
597 // Enqueue all delayed tasks that should be running now. | 549 // Enqueue all delayed tasks that should be running now. |
598 while (!main_thread_only().delayed_incoming_queue.empty()) { | 550 while (!main_thread_only().delayed_incoming_queue.empty()) { |
599 DelayedRunTimeQueue::iterator next_task = | 551 DelayedRunTimeQueue::iterator next_task = |
600 main_thread_only().delayed_incoming_queue.begin(); | 552 main_thread_only().delayed_incoming_queue.begin(); |
601 if (next_task->delayed_run_time > lazy_now->Now()) | 553 if (next_task->delayed_run_time > lazy_now->Now()) |
602 break; | 554 break; |
603 // TODO(alexclarke): Use extract() when C++17 is allowed. | 555 // TODO(alexclarke): Use extract() when C++17 is allowed. |
604 Task& task = const_cast<Task&>(*next_task); | 556 Task& task = const_cast<Task&>(*next_task); |
605 task.set_enqueue_order( | 557 task.set_enqueue_order( |
606 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 558 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
607 main_thread_only().delayed_work_queue->Push(std::move(task)); | 559 main_thread_only().delayed_work_queue->Push(std::move(task)); |
608 main_thread_only().delayed_incoming_queue.erase(next_task); | 560 main_thread_only().delayed_incoming_queue.erase(next_task); |
609 } | 561 } |
610 } | 562 } |
611 | 563 |
612 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, | 564 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { |
613 bool should_trigger_wakeup, | |
614 const Task* previous_task) { | |
615 if (!main_thread_only().task_queue_manager) | 565 if (!main_thread_only().task_queue_manager) |
616 return; | 566 return; |
617 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) | |
618 return; | |
619 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 567 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
620 TraceQueueSize(false); | 568 TraceQueueSize(false); |
621 } | 569 } |
622 | 570 |
623 void TaskQueueImpl::UpdateImmediateWorkQueue(bool should_trigger_wakeup, | 571 void TaskQueueImpl::UpdateImmediateWorkQueue() { |
624 const Task* previous_task) { | |
625 DCHECK(main_thread_only().immediate_work_queue->Empty()); | 572 DCHECK(main_thread_only().immediate_work_queue->Empty()); |
626 base::AutoLock lock(any_thread_lock_); | 573 base::AutoLock lock(any_thread_lock_); |
627 if (!main_thread_only().task_queue_manager) | 574 if (!main_thread_only().task_queue_manager) |
628 return; | 575 return; |
629 if (!ShouldAutoPumpImmediateQueueLocked(should_trigger_wakeup, previous_task)) | |
630 return; | |
631 | 576 |
632 main_thread_only().immediate_work_queue->SwapLocked( | 577 main_thread_only().immediate_work_queue->SwapLocked( |
633 any_thread().immediate_incoming_queue); | 578 any_thread().immediate_incoming_queue); |
634 | 579 |
635 // |any_thread().immediate_incoming_queue| is now empty so | 580 // |any_thread().immediate_incoming_queue| is now empty so |
636 // TimeDomain::UpdateQueues no longer needs to consider this queue for | 581 // TimeDomain::UpdateQueues no longer needs to consider this queue for |
637 // reloading. | 582 // reloading. |
638 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 583 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
639 } | 584 } |
640 | 585 |
(...skipping 15 matching lines...) Expand all Loading... |
656 any_thread_lock_.AssertAcquired(); | 601 any_thread_lock_.AssertAcquired(); |
657 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), | 602 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), |
658 any_thread().immediate_incoming_queue.size() + | 603 any_thread().immediate_incoming_queue.size() + |
659 main_thread_only().immediate_work_queue->Size() + | 604 main_thread_only().immediate_work_queue->Size() + |
660 main_thread_only().delayed_work_queue->Size() + | 605 main_thread_only().delayed_work_queue->Size() + |
661 main_thread_only().delayed_incoming_queue.size()); | 606 main_thread_only().delayed_incoming_queue.size()); |
662 if (!is_locked) | 607 if (!is_locked) |
663 any_thread_lock_.Release(); | 608 any_thread_lock_.Release(); |
664 } | 609 } |
665 | 610 |
666 void TaskQueueImpl::SetPumpPolicy(PumpPolicy pump_policy) { | |
667 base::AutoLock lock(any_thread_lock_); | |
668 if (pump_policy == PumpPolicy::AUTO && | |
669 any_thread().pump_policy != PumpPolicy::AUTO) { | |
670 LazyNow lazy_now(main_thread_only().time_domain->CreateLazyNow()); | |
671 PumpQueueLocked(&lazy_now, true); | |
672 } | |
673 any_thread().pump_policy = pump_policy; | |
674 main_thread_only().pump_policy = pump_policy; | |
675 } | |
676 | |
677 TaskQueue::PumpPolicy TaskQueueImpl::GetPumpPolicy() const { | |
678 return main_thread_only().pump_policy; | |
679 } | |
680 | |
681 void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) { | |
682 TRACE_EVENT1(disabled_by_default_tracing_category_, | |
683 "TaskQueueImpl::PumpQueueLocked", "queue", name_); | |
684 TaskQueueManager* task_queue_manager = any_thread().task_queue_manager; | |
685 if (!task_queue_manager) | |
686 return; | |
687 | |
688 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | |
689 | |
690 while (!any_thread().immediate_incoming_queue.empty()) { | |
691 ComparatorQueue::iterator it = | |
692 any_thread().immediate_incoming_queue.begin(); | |
693 main_thread_only().immediate_work_queue->Push( | |
694 std::move(const_cast<Task&>(*it))); | |
695 any_thread().immediate_incoming_queue.erase(it); | |
696 } | |
697 | |
698 // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no | |
699 // longer needs to consider this queue for reloading. | |
700 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | |
701 | |
702 if (main_thread_only().immediate_work_queue->Empty() && | |
703 main_thread_only().delayed_work_queue->Empty()) { | |
704 return; | |
705 } | |
706 | |
707 if (may_post_dowork) | |
708 task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | |
709 } | |
710 | |
711 void TaskQueueImpl::PumpQueue(LazyNow* lazy_now, bool may_post_dowork) { | |
712 base::AutoLock lock(any_thread_lock_); | |
713 PumpQueueLocked(lazy_now, may_post_dowork); | |
714 } | |
715 | |
716 const char* TaskQueueImpl::GetName() const { | 611 const char* TaskQueueImpl::GetName() const { |
717 return name_; | 612 return name_; |
718 } | 613 } |
719 | 614 |
720 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { | 615 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { |
721 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) | 616 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) |
722 return; | 617 return; |
723 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, | 618 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, |
724 priority); | 619 priority); |
725 } | 620 } |
726 | 621 |
727 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { | 622 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
728 size_t set_index = immediate_work_queue()->work_queue_set_index(); | 623 size_t set_index = immediate_work_queue()->work_queue_set_index(); |
729 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); | 624 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); |
730 return static_cast<TaskQueue::QueuePriority>(set_index); | 625 return static_cast<TaskQueue::QueuePriority>(set_index); |
731 } | 626 } |
732 | 627 |
733 // static | 628 // static |
734 const char* TaskQueueImpl::PumpPolicyToString( | |
735 TaskQueue::PumpPolicy pump_policy) { | |
736 switch (pump_policy) { | |
737 case TaskQueue::PumpPolicy::AUTO: | |
738 return "auto"; | |
739 case TaskQueue::PumpPolicy::AFTER_WAKEUP: | |
740 return "after_wakeup"; | |
741 case TaskQueue::PumpPolicy::MANUAL: | |
742 return "manual"; | |
743 default: | |
744 NOTREACHED(); | |
745 return nullptr; | |
746 } | |
747 } | |
748 | |
749 // static | |
750 const char* TaskQueueImpl::WakeupPolicyToString( | |
751 TaskQueue::WakeupPolicy wakeup_policy) { | |
752 switch (wakeup_policy) { | |
753 case TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES: | |
754 return "can_wake_other_queues"; | |
755 case TaskQueue::WakeupPolicy::DONT_WAKE_OTHER_QUEUES: | |
756 return "dont_wake_other_queues"; | |
757 default: | |
758 NOTREACHED(); | |
759 return nullptr; | |
760 } | |
761 } | |
762 | |
763 // static | |
764 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) { | 629 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) { |
765 switch (priority) { | 630 switch (priority) { |
766 case CONTROL_PRIORITY: | 631 case CONTROL_PRIORITY: |
767 return "control"; | 632 return "control"; |
768 case HIGH_PRIORITY: | 633 case HIGH_PRIORITY: |
769 return "high"; | 634 return "high"; |
770 case NORMAL_PRIORITY: | 635 case NORMAL_PRIORITY: |
771 return "normal"; | 636 return "normal"; |
772 case BEST_EFFORT_PRIORITY: | 637 case BEST_EFFORT_PRIORITY: |
773 return "best_effort"; | 638 return "best_effort"; |
774 default: | 639 default: |
775 NOTREACHED(); | 640 NOTREACHED(); |
776 return nullptr; | 641 return nullptr; |
777 } | 642 } |
778 } | 643 } |
779 | 644 |
780 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 645 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
781 base::AutoLock lock(any_thread_lock_); | 646 base::AutoLock lock(any_thread_lock_); |
782 state->BeginDictionary(); | 647 state->BeginDictionary(); |
783 state->SetString("name", GetName()); | 648 state->SetString("name", GetName()); |
784 state->SetBoolean("enabled", main_thread_only().is_enabled); | 649 state->SetBoolean("enabled", main_thread_only().is_enabled); |
785 state->SetString("time_domain_name", | 650 state->SetString("time_domain_name", |
786 main_thread_only().time_domain->GetName()); | 651 main_thread_only().time_domain->GetName()); |
787 state->SetString("pump_policy", PumpPolicyToString(any_thread().pump_policy)); | |
788 state->SetString("wakeup_policy", WakeupPolicyToString(wakeup_policy_)); | |
789 bool verbose_tracing_enabled = false; | 652 bool verbose_tracing_enabled = false; |
790 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 653 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
791 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); | 654 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); |
792 state->SetInteger("immediate_incoming_queue_size", | 655 state->SetInteger("immediate_incoming_queue_size", |
793 any_thread().immediate_incoming_queue.size()); | 656 any_thread().immediate_incoming_queue.size()); |
794 state->SetInteger("delayed_incoming_queue_size", | 657 state->SetInteger("delayed_incoming_queue_size", |
795 main_thread_only().delayed_incoming_queue.size()); | 658 main_thread_only().delayed_incoming_queue.size()); |
796 state->SetInteger("immediate_work_queue_size", | 659 state->SetInteger("immediate_work_queue_size", |
797 main_thread_only().immediate_work_queue->Size()); | 660 main_thread_only().immediate_work_queue->Size()); |
798 state->SetInteger("delayed_work_queue_size", | 661 state->SetInteger("delayed_work_queue_size", |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 | 740 |
878 base::AutoLock lock(any_thread_lock_); | 741 base::AutoLock lock(any_thread_lock_); |
879 return any_thread().time_domain; | 742 return any_thread().time_domain; |
880 } | 743 } |
881 | 744 |
882 void TaskQueueImpl::SetBlameContext( | 745 void TaskQueueImpl::SetBlameContext( |
883 base::trace_event::BlameContext* blame_context) { | 746 base::trace_event::BlameContext* blame_context) { |
884 main_thread_only().blame_context = blame_context; | 747 main_thread_only().blame_context = blame_context; |
885 } | 748 } |
886 | 749 |
| 750 EnqueueOrder TaskQueueImpl::GetNewestImmediateTaskEnqueueOrder() const { |
| 751 base::AutoLock lock(any_thread_lock_); |
| 752 if (!any_thread().immediate_incoming_queue.empty()) |
| 753 return any_thread().immediate_incoming_queue.rbegin()->enqueue_order(); |
| 754 const Task* task = main_thread_only().immediate_work_queue->GetBackTask(); |
| 755 if (task) |
| 756 return task->enqueue_order(); |
| 757 return 0; |
| 758 } |
| 759 |
| 760 EnqueueOrder TaskQueueImpl::GetNewestReadyDelayedTaskEnqueueOrder() { |
| 761 LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow(); |
| 762 MoveReadyDelayedTasksToDelayedWorkQueue(&lazy_now); |
| 763 const Task* task = main_thread_only().delayed_work_queue->GetBackTask(); |
| 764 if (task) |
| 765 return task->enqueue_order(); |
| 766 return 0; |
| 767 } |
| 768 |
| 769 void TaskQueueImpl::InsertFence() { |
| 770 if (!main_thread_only().task_queue_manager) |
| 771 return; |
| 772 |
| 773 EnqueueOrder next_immediate = GetNewestImmediateTaskEnqueueOrder(); |
| 774 EnqueueOrder next_delayed = GetNewestReadyDelayedTaskEnqueueOrder(); |
| 775 |
| 776 bool task_unblocked = |
| 777 main_thread_only().immediate_work_queue->InsertFence(next_immediate); |
| 778 task_unblocked |= |
| 779 main_thread_only().delayed_work_queue->InsertFence(next_delayed); |
| 780 |
| 781 if (!task_unblocked) |
| 782 task_unblocked |= HasPendingImmediateWork(); |
| 783 |
| 784 if (main_thread_only().is_enabled && task_unblocked) { |
| 785 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 786 FROM_HERE); |
| 787 } |
| 788 } |
| 789 |
| 790 void TaskQueueImpl::RemoveFence() { |
| 791 if (!main_thread_only().task_queue_manager) |
| 792 return; |
| 793 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 794 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 795 |
| 796 if (!task_unblocked) |
| 797 task_unblocked |= HasPendingImmediateWork(); |
| 798 |
| 799 if (main_thread_only().is_enabled && task_unblocked) { |
| 800 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 801 FROM_HERE); |
| 802 } |
| 803 } |
| 804 |
| 805 bool TaskQueueImpl::BlockedByFence() const { |
| 806 return main_thread_only().immediate_work_queue->fence_hit() && |
| 807 main_thread_only().delayed_work_queue->fence_hit(); |
| 808 } |
| 809 |
887 // static | 810 // static |
888 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, | 811 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
889 base::trace_event::TracedValue* state) { | 812 base::trace_event::TracedValue* state) { |
890 for (const Task& task : queue) { | 813 for (const Task& task : queue) { |
891 TaskAsValueInto(task, state); | 814 TaskAsValueInto(task, state); |
892 } | 815 } |
893 } | 816 } |
894 | 817 |
895 // static | 818 // static |
896 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, | 819 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
(...skipping 19 matching lines...) Expand all Loading... |
916 state->SetBoolean("is_high_res", task.is_high_res); | 839 state->SetBoolean("is_high_res", task.is_high_res); |
917 state->SetDouble( | 840 state->SetDouble( |
918 "delayed_run_time", | 841 "delayed_run_time", |
919 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 842 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
920 state->EndDictionary(); | 843 state->EndDictionary(); |
921 } | 844 } |
922 | 845 |
923 } // namespace internal | 846 } // namespace internal |
924 } // namespace scheduler | 847 } // namespace scheduler |
925 } // namespace blink | 848 } // namespace blink |
OLD | NEW |