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), |
201 is_enabled(true), | 193 is_enabled(true), |
202 blame_context(nullptr) {} | 194 blame_context(nullptr), |
| 195 current_fence(0) {} |
203 | 196 |
204 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} | 197 TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {} |
205 | 198 |
206 void TaskQueueImpl::UnregisterTaskQueue() { | 199 void TaskQueueImpl::UnregisterTaskQueue() { |
207 base::AutoLock lock(any_thread_lock_); | 200 base::AutoLock lock(any_thread_lock_); |
208 if (main_thread_only().time_domain) | 201 if (main_thread_only().time_domain) |
209 main_thread_only().time_domain->UnregisterQueue(this); | 202 main_thread_only().time_domain->UnregisterQueue(this); |
210 if (!any_thread().task_queue_manager) | 203 if (!any_thread().task_queue_manager) |
211 return; | 204 return; |
212 any_thread().time_domain = nullptr; | 205 any_thread().time_domain = nullptr; |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
442 PushOntoImmediateIncomingQueueLocked( | 435 PushOntoImmediateIncomingQueueLocked( |
443 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, | 436 Task(FROM_HERE, base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this, |
444 base::Passed(&pending_task)), | 437 base::Passed(&pending_task)), |
445 base::TimeTicks(), thread_hop_task_sequence_number, false, | 438 base::TimeTicks(), thread_hop_task_sequence_number, false, |
446 thread_hop_task_sequence_number)); | 439 thread_hop_task_sequence_number)); |
447 } | 440 } |
448 | 441 |
449 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { | 442 void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) { |
450 if (any_thread().immediate_incoming_queue.empty()) | 443 if (any_thread().immediate_incoming_queue.empty()) |
451 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); | 444 any_thread().time_domain->RegisterAsUpdatableTaskQueue(this); |
452 if (any_thread().pump_policy == PumpPolicy::AUTO && | 445 // If the |immediate_incoming_queue| is empty we need a DoWork posted to make |
453 any_thread().immediate_incoming_queue.empty()) { | 446 // it run. |
454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); | 447 if (any_thread().immediate_incoming_queue.empty()) { |
| 448 // 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. |
| 450 if (base::PlatformThread::CurrentId() == thread_id_) { |
| 451 if (main_thread_only().is_enabled && !BlockedByFenceLocked()) |
| 452 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 453 } else { |
| 454 any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE); |
| 455 } |
455 } | 456 } |
456 any_thread().task_queue_manager->DidQueueTask(pending_task); | 457 any_thread().task_queue_manager->DidQueueTask(pending_task); |
457 // We expect |pending_task| to be inserted at the end. Amoritized O(1). | 458 // We expect |pending_task| to be inserted at the end. Amoritized O(1). |
458 any_thread().immediate_incoming_queue.insert( | 459 any_thread().immediate_incoming_queue.insert( |
459 any_thread().immediate_incoming_queue.end(), | 460 any_thread().immediate_incoming_queue.end(), |
460 std::move(pending_task)); | 461 std::move(pending_task)); |
461 DCHECK_EQ(pending_task.enqueue_order(), | 462 DCHECK_EQ(pending_task.enqueue_order(), |
462 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); | 463 any_thread().immediate_incoming_queue.rbegin()->enqueue_order()); |
463 TraceQueueSize(true); | 464 TraceQueueSize(true); |
464 } | 465 } |
(...skipping 17 matching lines...) Expand all Loading... |
482 TraceQueueSize(false); | 483 TraceQueueSize(false); |
483 } | 484 } |
484 | 485 |
485 void TaskQueueImpl::SetQueueEnabled(bool enabled) { | 486 void TaskQueueImpl::SetQueueEnabled(bool enabled) { |
486 if (main_thread_only().is_enabled == enabled) | 487 if (main_thread_only().is_enabled == enabled) |
487 return; | 488 return; |
488 main_thread_only().is_enabled = enabled; | 489 main_thread_only().is_enabled = enabled; |
489 if (!main_thread_only().task_queue_manager) | 490 if (!main_thread_only().task_queue_manager) |
490 return; | 491 return; |
491 if (enabled) { | 492 if (enabled) { |
| 493 // Note it's the job of the selector to tell the TaskQueueManager if |
| 494 // a DoWork needs posting. |
492 main_thread_only().task_queue_manager->selector_.EnableQueue(this); | 495 main_thread_only().task_queue_manager->selector_.EnableQueue(this); |
493 } else { | 496 } else { |
494 main_thread_only().task_queue_manager->selector_.DisableQueue(this); | 497 main_thread_only().task_queue_manager->selector_.DisableQueue(this); |
495 } | 498 } |
496 } | 499 } |
497 | 500 |
498 bool TaskQueueImpl::IsQueueEnabled() const { | 501 bool TaskQueueImpl::IsQueueEnabled() const { |
499 return main_thread_only().is_enabled; | 502 return main_thread_only().is_enabled; |
500 } | 503 } |
501 | 504 |
502 bool TaskQueueImpl::IsEmpty() const { | 505 bool TaskQueueImpl::IsEmpty() const { |
503 if (!main_thread_only().delayed_work_queue->Empty() || | 506 if (!main_thread_only().delayed_work_queue->Empty() || |
504 !main_thread_only().immediate_work_queue->Empty()) { | 507 !main_thread_only().immediate_work_queue->Empty()) { |
505 return false; | 508 return false; |
506 } | 509 } |
507 | 510 |
508 base::AutoLock lock(any_thread_lock_); | 511 base::AutoLock lock(any_thread_lock_); |
509 return any_thread().immediate_incoming_queue.empty() && | 512 return any_thread().immediate_incoming_queue.empty() && |
510 main_thread_only().delayed_incoming_queue.empty(); | 513 main_thread_only().delayed_incoming_queue.empty(); |
511 } | 514 } |
512 | 515 |
513 bool TaskQueueImpl::HasPendingImmediateWork() const { | 516 bool TaskQueueImpl::HasPendingImmediateWork() const { |
| 517 // Any work queue tasks count as immediate work. |
514 if (!main_thread_only().delayed_work_queue->Empty() || | 518 if (!main_thread_only().delayed_work_queue->Empty() || |
515 !main_thread_only().immediate_work_queue->Empty()) { | 519 !main_thread_only().immediate_work_queue->Empty()) { |
516 return true; | 520 return true; |
517 } | 521 } |
518 | 522 |
519 return NeedsPumping(); | 523 // Tasks on |delayed_incoming_queue| that could run now, count as |
520 } | 524 // immediate work. |
521 | 525 if (!main_thread_only().delayed_incoming_queue.empty() && |
522 bool TaskQueueImpl::NeedsPumping() const { | 526 main_thread_only().delayed_incoming_queue.begin()->delayed_run_time <= |
523 if (!main_thread_only().immediate_work_queue->Empty()) | 527 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; | 528 return true; |
568 } | 529 } |
569 | 530 |
570 return task->enqueue_order() < enqueue_order; | 531 // Finally tasks on |immediate_incoming_queue| count as immediate work. |
571 } | 532 base::AutoLock lock(any_thread_lock_); |
572 | 533 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 } | 534 } |
595 | 535 |
596 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { | 536 void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) { |
597 // Enqueue all delayed tasks that should be running now. | 537 // Enqueue all delayed tasks that should be running now. |
598 while (!main_thread_only().delayed_incoming_queue.empty()) { | 538 while (!main_thread_only().delayed_incoming_queue.empty()) { |
599 DelayedRunTimeQueue::iterator next_task = | 539 DelayedRunTimeQueue::iterator next_task = |
600 main_thread_only().delayed_incoming_queue.begin(); | 540 main_thread_only().delayed_incoming_queue.begin(); |
601 if (next_task->delayed_run_time > lazy_now->Now()) | 541 if (next_task->delayed_run_time > lazy_now->Now()) |
602 break; | 542 break; |
603 // TODO(alexclarke): Use extract() when C++17 is allowed. | 543 // TODO(alexclarke): Use extract() when C++17 is allowed. |
604 Task& task = const_cast<Task&>(*next_task); | 544 Task& task = const_cast<Task&>(*next_task); |
605 task.set_enqueue_order( | 545 task.set_enqueue_order( |
606 main_thread_only().task_queue_manager->GetNextSequenceNumber()); | 546 main_thread_only().task_queue_manager->GetNextSequenceNumber()); |
607 main_thread_only().delayed_work_queue->Push(std::move(task)); | 547 main_thread_only().delayed_work_queue->Push(std::move(task)); |
608 main_thread_only().delayed_incoming_queue.erase(next_task); | 548 main_thread_only().delayed_incoming_queue.erase(next_task); |
609 } | 549 } |
610 } | 550 } |
611 | 551 |
612 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now, | 552 void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now) { |
613 bool should_trigger_wakeup, | |
614 const Task* previous_task) { | |
615 if (!main_thread_only().task_queue_manager) | 553 if (!main_thread_only().task_queue_manager) |
616 return; | 554 return; |
617 if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task)) | |
618 return; | |
619 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); | 555 MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now); |
620 TraceQueueSize(false); | 556 TraceQueueSize(false); |
621 } | 557 } |
622 | 558 |
623 void TaskQueueImpl::UpdateImmediateWorkQueue(bool should_trigger_wakeup, | 559 void TaskQueueImpl::UpdateImmediateWorkQueue() { |
624 const Task* previous_task) { | |
625 DCHECK(main_thread_only().immediate_work_queue->Empty()); | 560 DCHECK(main_thread_only().immediate_work_queue->Empty()); |
626 base::AutoLock lock(any_thread_lock_); | 561 base::AutoLock lock(any_thread_lock_); |
627 if (!main_thread_only().task_queue_manager) | 562 if (!main_thread_only().task_queue_manager) |
628 return; | 563 return; |
629 if (!ShouldAutoPumpImmediateQueueLocked(should_trigger_wakeup, previous_task)) | |
630 return; | |
631 | 564 |
632 main_thread_only().immediate_work_queue->SwapLocked( | 565 main_thread_only().immediate_work_queue->SwapLocked( |
633 any_thread().immediate_incoming_queue); | 566 any_thread().immediate_incoming_queue); |
634 | 567 |
635 // |any_thread().immediate_incoming_queue| is now empty so | 568 // |any_thread().immediate_incoming_queue| is now empty so |
636 // TimeDomain::UpdateQueues no longer needs to consider this queue for | 569 // TimeDomain::UpdateQueues no longer needs to consider this queue for |
637 // reloading. | 570 // reloading. |
638 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); | 571 main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this); |
639 } | 572 } |
640 | 573 |
(...skipping 15 matching lines...) Expand all Loading... |
656 any_thread_lock_.AssertAcquired(); | 589 any_thread_lock_.AssertAcquired(); |
657 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), | 590 TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(), |
658 any_thread().immediate_incoming_queue.size() + | 591 any_thread().immediate_incoming_queue.size() + |
659 main_thread_only().immediate_work_queue->Size() + | 592 main_thread_only().immediate_work_queue->Size() + |
660 main_thread_only().delayed_work_queue->Size() + | 593 main_thread_only().delayed_work_queue->Size() + |
661 main_thread_only().delayed_incoming_queue.size()); | 594 main_thread_only().delayed_incoming_queue.size()); |
662 if (!is_locked) | 595 if (!is_locked) |
663 any_thread_lock_.Release(); | 596 any_thread_lock_.Release(); |
664 } | 597 } |
665 | 598 |
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 { | 599 const char* TaskQueueImpl::GetName() const { |
717 return name_; | 600 return name_; |
718 } | 601 } |
719 | 602 |
720 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { | 603 void TaskQueueImpl::SetQueuePriority(QueuePriority priority) { |
721 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) | 604 if (!main_thread_only().task_queue_manager || priority == GetQueuePriority()) |
722 return; | 605 return; |
723 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, | 606 main_thread_only().task_queue_manager->selector_.SetQueuePriority(this, |
724 priority); | 607 priority); |
725 } | 608 } |
726 | 609 |
727 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { | 610 TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const { |
728 size_t set_index = immediate_work_queue()->work_queue_set_index(); | 611 size_t set_index = immediate_work_queue()->work_queue_set_index(); |
729 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); | 612 DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index()); |
730 return static_cast<TaskQueue::QueuePriority>(set_index); | 613 return static_cast<TaskQueue::QueuePriority>(set_index); |
731 } | 614 } |
732 | 615 |
733 // static | 616 // 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) { | 617 const char* TaskQueueImpl::PriorityToString(QueuePriority priority) { |
765 switch (priority) { | 618 switch (priority) { |
766 case CONTROL_PRIORITY: | 619 case CONTROL_PRIORITY: |
767 return "control"; | 620 return "control"; |
768 case HIGH_PRIORITY: | 621 case HIGH_PRIORITY: |
769 return "high"; | 622 return "high"; |
770 case NORMAL_PRIORITY: | 623 case NORMAL_PRIORITY: |
771 return "normal"; | 624 return "normal"; |
772 case BEST_EFFORT_PRIORITY: | 625 case BEST_EFFORT_PRIORITY: |
773 return "best_effort"; | 626 return "best_effort"; |
774 default: | 627 default: |
775 NOTREACHED(); | 628 NOTREACHED(); |
776 return nullptr; | 629 return nullptr; |
777 } | 630 } |
778 } | 631 } |
779 | 632 |
780 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { | 633 void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const { |
781 base::AutoLock lock(any_thread_lock_); | 634 base::AutoLock lock(any_thread_lock_); |
782 state->BeginDictionary(); | 635 state->BeginDictionary(); |
783 state->SetString("name", GetName()); | 636 state->SetString("name", GetName()); |
784 state->SetBoolean("enabled", main_thread_only().is_enabled); | 637 state->SetBoolean("enabled", main_thread_only().is_enabled); |
785 state->SetString("time_domain_name", | 638 state->SetString("time_domain_name", |
786 main_thread_only().time_domain->GetName()); | 639 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; | 640 bool verbose_tracing_enabled = false; |
790 TRACE_EVENT_CATEGORY_GROUP_ENABLED( | 641 TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
791 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); | 642 disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled); |
792 state->SetInteger("immediate_incoming_queue_size", | 643 state->SetInteger("immediate_incoming_queue_size", |
793 any_thread().immediate_incoming_queue.size()); | 644 any_thread().immediate_incoming_queue.size()); |
794 state->SetInteger("delayed_incoming_queue_size", | 645 state->SetInteger("delayed_incoming_queue_size", |
795 main_thread_only().delayed_incoming_queue.size()); | 646 main_thread_only().delayed_incoming_queue.size()); |
796 state->SetInteger("immediate_work_queue_size", | 647 state->SetInteger("immediate_work_queue_size", |
797 main_thread_only().immediate_work_queue->Size()); | 648 main_thread_only().immediate_work_queue->Size()); |
798 state->SetInteger("delayed_work_queue_size", | 649 state->SetInteger("delayed_work_queue_size", |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
877 | 728 |
878 base::AutoLock lock(any_thread_lock_); | 729 base::AutoLock lock(any_thread_lock_); |
879 return any_thread().time_domain; | 730 return any_thread().time_domain; |
880 } | 731 } |
881 | 732 |
882 void TaskQueueImpl::SetBlameContext( | 733 void TaskQueueImpl::SetBlameContext( |
883 base::trace_event::BlameContext* blame_context) { | 734 base::trace_event::BlameContext* blame_context) { |
884 main_thread_only().blame_context = blame_context; | 735 main_thread_only().blame_context = blame_context; |
885 } | 736 } |
886 | 737 |
| 738 void TaskQueueImpl::InsertFence() { |
| 739 if (!main_thread_only().task_queue_manager) |
| 740 return; |
| 741 |
| 742 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 743 main_thread_only().current_fence = |
| 744 main_thread_only().task_queue_manager->GetNextSequenceNumber(); |
| 745 |
| 746 // Tasks posted after this point will have a strictly higher enqueue order |
| 747 // and will be blocked from running. |
| 748 bool task_unblocked = main_thread_only().immediate_work_queue->InsertFence( |
| 749 main_thread_only().current_fence); |
| 750 task_unblocked |= main_thread_only().delayed_work_queue->InsertFence( |
| 751 main_thread_only().current_fence); |
| 752 |
| 753 if (!task_unblocked && previous_fence) { |
| 754 base::AutoLock lock(any_thread_lock_); |
| 755 if (!any_thread().immediate_incoming_queue.empty() && |
| 756 any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 757 previous_fence && |
| 758 any_thread().immediate_incoming_queue.begin()->enqueue_order() < |
| 759 main_thread_only().current_fence) { |
| 760 task_unblocked = true; |
| 761 } |
| 762 } |
| 763 |
| 764 if (main_thread_only().is_enabled && task_unblocked) { |
| 765 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 766 FROM_HERE); |
| 767 } |
| 768 } |
| 769 |
| 770 void TaskQueueImpl::RemoveFence() { |
| 771 if (!main_thread_only().task_queue_manager) |
| 772 return; |
| 773 |
| 774 EnqueueOrder previous_fence = main_thread_only().current_fence; |
| 775 main_thread_only().current_fence = 0; |
| 776 |
| 777 bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence(); |
| 778 task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence(); |
| 779 |
| 780 if (!task_unblocked && previous_fence) { |
| 781 base::AutoLock lock(any_thread_lock_); |
| 782 if (!any_thread().immediate_incoming_queue.empty() && |
| 783 any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 784 previous_fence) { |
| 785 task_unblocked = true; |
| 786 } |
| 787 } |
| 788 |
| 789 if (main_thread_only().is_enabled && task_unblocked) { |
| 790 main_thread_only().task_queue_manager->MaybeScheduleImmediateWork( |
| 791 FROM_HERE); |
| 792 } |
| 793 } |
| 794 |
| 795 bool TaskQueueImpl::BlockedByFence() const { |
| 796 if (!main_thread_only().current_fence) |
| 797 return false; |
| 798 |
| 799 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 800 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 801 return false; |
| 802 } |
| 803 |
| 804 base::AutoLock lock(any_thread_lock_); |
| 805 if (any_thread().immediate_incoming_queue.empty()) |
| 806 return true; |
| 807 |
| 808 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 809 main_thread_only().current_fence; |
| 810 } |
| 811 |
| 812 bool TaskQueueImpl::BlockedByFenceLocked() const { |
| 813 if (!main_thread_only().current_fence) |
| 814 return false; |
| 815 |
| 816 if (!main_thread_only().immediate_work_queue->BlockedByFence() || |
| 817 !main_thread_only().delayed_work_queue->BlockedByFence()) { |
| 818 return false; |
| 819 } |
| 820 |
| 821 if (any_thread().immediate_incoming_queue.empty()) |
| 822 return true; |
| 823 |
| 824 return any_thread().immediate_incoming_queue.begin()->enqueue_order() > |
| 825 main_thread_only().current_fence; |
| 826 } |
| 827 |
887 // static | 828 // static |
888 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, | 829 void TaskQueueImpl::QueueAsValueInto(const ComparatorQueue& queue, |
889 base::trace_event::TracedValue* state) { | 830 base::trace_event::TracedValue* state) { |
890 for (const Task& task : queue) { | 831 for (const Task& task : queue) { |
891 TaskAsValueInto(task, state); | 832 TaskAsValueInto(task, state); |
892 } | 833 } |
893 } | 834 } |
894 | 835 |
895 // static | 836 // static |
896 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, | 837 void TaskQueueImpl::QueueAsValueInto(const DelayedRunTimeQueue& queue, |
(...skipping 19 matching lines...) Expand all Loading... |
916 state->SetBoolean("is_high_res", task.is_high_res); | 857 state->SetBoolean("is_high_res", task.is_high_res); |
917 state->SetDouble( | 858 state->SetDouble( |
918 "delayed_run_time", | 859 "delayed_run_time", |
919 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); | 860 (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L); |
920 state->EndDictionary(); | 861 state->EndDictionary(); |
921 } | 862 } |
922 | 863 |
923 } // namespace internal | 864 } // namespace internal |
924 } // namespace scheduler | 865 } // namespace scheduler |
925 } // namespace blink | 866 } // namespace blink |
OLD | NEW |