Index: components/scheduler/base/task_queue_selector.cc |
diff --git a/components/scheduler/base/task_queue_selector.cc b/components/scheduler/base/task_queue_selector.cc |
deleted file mode 100644 |
index 9db8ab9c2de43124bb2b04565a02beb9d256a06a..0000000000000000000000000000000000000000 |
--- a/components/scheduler/base/task_queue_selector.cc |
+++ /dev/null |
@@ -1,380 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "components/scheduler/base/task_queue_selector.h" |
- |
-#include "base/logging.h" |
-#include "base/trace_event/trace_event_argument.h" |
-#include "components/scheduler/base/task_queue_impl.h" |
-#include "components/scheduler/base/work_queue.h" |
- |
-namespace scheduler { |
-namespace internal { |
- |
-TaskQueueSelector::TaskQueueSelector() |
- : enabled_selector_(this, "enabled"), |
- blocked_selector_(this, "blocked"), |
- immediate_starvation_count_(0), |
- high_priority_starvation_count_(0), |
- num_blocked_queues_to_report_(0), |
- task_queue_selector_observer_(nullptr) {} |
- |
-TaskQueueSelector::~TaskQueueSelector() {} |
- |
-void TaskQueueSelector::AddQueue(internal::TaskQueueImpl* queue) { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- DCHECK(queue->IsQueueEnabled()); |
- enabled_selector_.AddQueue(queue, TaskQueue::NORMAL_PRIORITY); |
-} |
- |
-void TaskQueueSelector::RemoveQueue(internal::TaskQueueImpl* queue) { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- if (queue->IsQueueEnabled()) { |
- enabled_selector_.RemoveQueue(queue); |
-// The #if DCHECK_IS_ON() shouldn't be necessary but this doesn't compile on |
-// chromeos bots without it :( |
-#if DCHECK_IS_ON() |
- DCHECK(!blocked_selector_.CheckContainsQueueForTest(queue)); |
-#endif |
- } else if (queue->should_report_when_execution_blocked()) { |
- DCHECK_GT(num_blocked_queues_to_report_, 0u); |
- num_blocked_queues_to_report_--; |
- blocked_selector_.RemoveQueue(queue); |
-#if DCHECK_IS_ON() |
- DCHECK(!enabled_selector_.CheckContainsQueueForTest(queue)); |
-#endif |
- } |
-} |
- |
-void TaskQueueSelector::EnableQueue(internal::TaskQueueImpl* queue) { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- DCHECK(queue->IsQueueEnabled()); |
- if (queue->should_report_when_execution_blocked()) { |
- DCHECK_GT(num_blocked_queues_to_report_, 0u); |
- num_blocked_queues_to_report_--; |
- blocked_selector_.RemoveQueue(queue); |
- } |
- enabled_selector_.AddQueue(queue, queue->GetQueuePriority()); |
- if (task_queue_selector_observer_) |
- task_queue_selector_observer_->OnTaskQueueEnabled(queue); |
-} |
- |
-void TaskQueueSelector::DisableQueue(internal::TaskQueueImpl* queue) { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- DCHECK(!queue->IsQueueEnabled()); |
- enabled_selector_.RemoveQueue(queue); |
- if (queue->should_report_when_execution_blocked()) { |
- blocked_selector_.AddQueue(queue, queue->GetQueuePriority()); |
- num_blocked_queues_to_report_++; |
- } |
-} |
- |
-void TaskQueueSelector::SetQueuePriority(internal::TaskQueueImpl* queue, |
- TaskQueue::QueuePriority priority) { |
- DCHECK_LT(priority, TaskQueue::QUEUE_PRIORITY_COUNT); |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- if (queue->IsQueueEnabled()) { |
- enabled_selector_.ChangeSetIndex(queue, priority); |
- } else if (queue->should_report_when_execution_blocked()) { |
- blocked_selector_.ChangeSetIndex(queue, priority); |
- } else { |
- // Normally blocked_selector_.ChangeSetIndex would assign the queue's |
- // priority, however if |queue->should_report_when_execution_blocked()| is |
- // false then the disabled queue is not in any set so we need to do it here. |
- queue->delayed_work_queue()->AssignSetIndex(priority); |
- queue->immediate_work_queue()->AssignSetIndex(priority); |
- } |
- DCHECK_EQ(priority, queue->GetQueuePriority()); |
-} |
- |
-TaskQueue::QueuePriority TaskQueueSelector::NextPriority( |
- TaskQueue::QueuePriority priority) { |
- DCHECK(priority < TaskQueue::QUEUE_PRIORITY_COUNT); |
- return static_cast<TaskQueue::QueuePriority>(static_cast<int>(priority) + 1); |
-} |
- |
-TaskQueueSelector::PrioritizingSelector::PrioritizingSelector( |
- TaskQueueSelector* task_queue_selector, |
- const char* name) |
- : task_queue_selector_(task_queue_selector), |
- delayed_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT, name), |
- immediate_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT, name) {} |
- |
-void TaskQueueSelector::PrioritizingSelector::AddQueue( |
- internal::TaskQueueImpl* queue, |
- TaskQueue::QueuePriority priority) { |
-#if DCHECK_IS_ON() |
- DCHECK(!CheckContainsQueueForTest(queue)); |
-#endif |
- delayed_work_queue_sets_.AddQueue(queue->delayed_work_queue(), priority); |
- immediate_work_queue_sets_.AddQueue(queue->immediate_work_queue(), priority); |
-#if DCHECK_IS_ON() |
- DCHECK(CheckContainsQueueForTest(queue)); |
-#endif |
-} |
- |
-void TaskQueueSelector::PrioritizingSelector::ChangeSetIndex( |
- internal::TaskQueueImpl* queue, |
- TaskQueue::QueuePriority priority) { |
-#if DCHECK_IS_ON() |
- DCHECK(CheckContainsQueueForTest(queue)); |
-#endif |
- delayed_work_queue_sets_.ChangeSetIndex(queue->delayed_work_queue(), |
- priority); |
- immediate_work_queue_sets_.ChangeSetIndex(queue->immediate_work_queue(), |
- priority); |
-#if DCHECK_IS_ON() |
- DCHECK(CheckContainsQueueForTest(queue)); |
-#endif |
-} |
- |
-void TaskQueueSelector::PrioritizingSelector::RemoveQueue( |
- internal::TaskQueueImpl* queue) { |
-#if DCHECK_IS_ON() |
- DCHECK(CheckContainsQueueForTest(queue)); |
-#endif |
- delayed_work_queue_sets_.RemoveQueue(queue->delayed_work_queue()); |
- immediate_work_queue_sets_.RemoveQueue(queue->immediate_work_queue()); |
- |
-#if DCHECK_IS_ON() |
- DCHECK(!CheckContainsQueueForTest(queue)); |
-#endif |
-} |
- |
-bool TaskQueueSelector::PrioritizingSelector:: |
- ChooseOldestImmediateTaskWithPriority(TaskQueue::QueuePriority priority, |
- WorkQueue** out_work_queue) const { |
- return immediate_work_queue_sets_.GetOldestQueueInSet(priority, |
- out_work_queue); |
-} |
- |
-bool TaskQueueSelector::PrioritizingSelector:: |
- ChooseOldestDelayedTaskWithPriority(TaskQueue::QueuePriority priority, |
- WorkQueue** out_work_queue) const { |
- return delayed_work_queue_sets_.GetOldestQueueInSet(priority, out_work_queue); |
-} |
- |
-bool TaskQueueSelector::PrioritizingSelector:: |
- ChooseOldestImmediateOrDelayedTaskWithPriority( |
- TaskQueue::QueuePriority priority, |
- bool* out_chose_delayed_over_immediate, |
- WorkQueue** out_work_queue) const { |
- WorkQueue* immediate_queue; |
- DCHECK_EQ(*out_chose_delayed_over_immediate, false); |
- if (immediate_work_queue_sets_.GetOldestQueueInSet(priority, |
- &immediate_queue)) { |
- WorkQueue* delayed_queue; |
- if (delayed_work_queue_sets_.GetOldestQueueInSet(priority, |
- &delayed_queue)) { |
- if (immediate_queue->ShouldRunBefore(delayed_queue)) { |
- *out_work_queue = immediate_queue; |
- } else { |
- *out_chose_delayed_over_immediate = true; |
- *out_work_queue = delayed_queue; |
- } |
- } else { |
- *out_work_queue = immediate_queue; |
- } |
- return true; |
- } |
- return delayed_work_queue_sets_.GetOldestQueueInSet(priority, out_work_queue); |
-} |
- |
-bool TaskQueueSelector::PrioritizingSelector::ChooseOldestWithPriority( |
- TaskQueue::QueuePriority priority, |
- bool* out_chose_delayed_over_immediate, |
- WorkQueue** out_work_queue) const { |
- // Select an immediate work queue if we are starving immediate tasks. |
- if (task_queue_selector_->immediate_starvation_count_ >= |
- kMaxDelayedStarvationTasks) { |
- if (ChooseOldestImmediateTaskWithPriority(priority, out_work_queue)) { |
- return true; |
- } |
- if (ChooseOldestDelayedTaskWithPriority(priority, out_work_queue)) { |
- return true; |
- } |
- return false; |
- } |
- return ChooseOldestImmediateOrDelayedTaskWithPriority( |
- priority, out_chose_delayed_over_immediate, out_work_queue); |
-} |
- |
-bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService( |
- TaskQueue::QueuePriority max_priority, |
- WorkQueue** out_work_queue, |
- bool* out_chose_delayed_over_immediate) { |
- DCHECK(task_queue_selector_->main_thread_checker_.CalledOnValidThread()); |
- DCHECK_EQ(*out_chose_delayed_over_immediate, false); |
- |
- // Always service the control queue if it has any work. |
- if (max_priority > TaskQueue::CONTROL_PRIORITY && |
- ChooseOldestWithPriority(TaskQueue::CONTROL_PRIORITY, |
- out_chose_delayed_over_immediate, |
- out_work_queue)) { |
- return true; |
- } |
- |
- // Select from the normal priority queue if we are starving it. |
- if (max_priority > TaskQueue::NORMAL_PRIORITY && |
- task_queue_selector_->high_priority_starvation_count_ >= |
- kMaxHighPriorityStarvationTasks && |
- ChooseOldestWithPriority(TaskQueue::NORMAL_PRIORITY, |
- out_chose_delayed_over_immediate, |
- out_work_queue)) { |
- return true; |
- } |
- // Otherwise choose in priority order. |
- for (TaskQueue::QueuePriority priority = TaskQueue::HIGH_PRIORITY; |
- priority < max_priority; priority = NextPriority(priority)) { |
- if (ChooseOldestWithPriority(priority, out_chose_delayed_over_immediate, |
- out_work_queue)) { |
- return true; |
- } |
- } |
- return false; |
-} |
- |
-#if DCHECK_IS_ON() || !defined(NDEBUG) |
-bool |
-TaskQueueSelector::PrioritizingSelector::CheckContainsQueueForTest( |
- const internal::TaskQueueImpl* queue) const { |
- bool contains_delayed_work_queue = |
- delayed_work_queue_sets_.ContainsWorkQueueForTest( |
- queue->delayed_work_queue()); |
- |
- bool contains_immediate_work_queue = |
- immediate_work_queue_sets_.ContainsWorkQueueForTest( |
- queue->immediate_work_queue()); |
- |
- DCHECK_EQ(contains_delayed_work_queue, contains_immediate_work_queue); |
- return contains_delayed_work_queue; |
-} |
-#endif |
- |
-bool TaskQueueSelector::SelectWorkQueueToService(WorkQueue** out_work_queue) { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- bool chose_delayed_over_immediate = false; |
- bool found_queue = enabled_selector_.SelectWorkQueueToService( |
- TaskQueue::QUEUE_PRIORITY_COUNT, out_work_queue, |
- &chose_delayed_over_immediate); |
- if (!found_queue) { |
- TrySelectingBlockedQueue(); |
- return false; |
- } |
- |
- TrySelectingBlockedQueueOverEnabledQueue(**out_work_queue); |
- DidSelectQueueWithPriority( |
- (*out_work_queue)->task_queue()->GetQueuePriority(), |
- chose_delayed_over_immediate); |
- return true; |
-} |
- |
-void TaskQueueSelector::TrySelectingBlockedQueue() { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- if (!num_blocked_queues_to_report_ || !task_queue_selector_observer_) |
- return; |
- WorkQueue* chosen_blocked_queue; |
- bool chose_delayed_over_immediate = false; |
- // There was nothing unblocked to run, see if we could have run a blocked |
- // task. |
- if (blocked_selector_.SelectWorkQueueToService( |
- TaskQueue::QUEUE_PRIORITY_COUNT, &chosen_blocked_queue, |
- &chose_delayed_over_immediate)) { |
- task_queue_selector_observer_->OnTriedToSelectBlockedWorkQueue( |
- chosen_blocked_queue); |
- } |
-} |
- |
-void TaskQueueSelector::TrySelectingBlockedQueueOverEnabledQueue( |
- const WorkQueue& chosen_enabled_queue) { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- if (!num_blocked_queues_to_report_ || !task_queue_selector_observer_) |
- return; |
- |
- TaskQueue::QueuePriority max_priority = |
- NextPriority(chosen_enabled_queue.task_queue()->GetQueuePriority()); |
- |
- WorkQueue* chosen_blocked_queue; |
- bool chose_delayed_over_immediate = false; |
- bool found_queue = blocked_selector_.SelectWorkQueueToService( |
- max_priority, &chosen_blocked_queue, &chose_delayed_over_immediate); |
- if (!found_queue) |
- return; |
- |
- // Check if the chosen blocked queue has a lower numerical priority than the |
- // chosen enabled queue. If so we would have chosen the blocked queue (since |
- // zero is the highest priority). |
- if (chosen_blocked_queue->task_queue()->GetQueuePriority() < |
- chosen_enabled_queue.task_queue()->GetQueuePriority()) { |
- task_queue_selector_observer_->OnTriedToSelectBlockedWorkQueue( |
- chosen_blocked_queue); |
- return; |
- } |
- DCHECK_EQ(chosen_blocked_queue->task_queue()->GetQueuePriority(), |
- chosen_enabled_queue.task_queue()->GetQueuePriority()); |
- // Otherwise there was an enabled and a blocked task with the same priority. |
- // The one with the older enqueue order wins. |
- if (chosen_blocked_queue->ShouldRunBefore(&chosen_enabled_queue)) { |
- task_queue_selector_observer_->OnTriedToSelectBlockedWorkQueue( |
- chosen_blocked_queue); |
- } |
-} |
- |
-void TaskQueueSelector::DidSelectQueueWithPriority( |
- TaskQueue::QueuePriority priority, |
- bool chose_delayed_over_immediate) { |
- switch (priority) { |
- case TaskQueue::CONTROL_PRIORITY: |
- break; |
- case TaskQueue::HIGH_PRIORITY: |
- high_priority_starvation_count_++; |
- break; |
- case TaskQueue::NORMAL_PRIORITY: |
- case TaskQueue::BEST_EFFORT_PRIORITY: |
- high_priority_starvation_count_ = 0; |
- break; |
- default: |
- NOTREACHED(); |
- } |
- if (chose_delayed_over_immediate) { |
- immediate_starvation_count_++; |
- } else { |
- immediate_starvation_count_ = 0; |
- } |
-} |
- |
-void TaskQueueSelector::AsValueInto( |
- base::trace_event::TracedValue* state) const { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- state->SetInteger("high_priority_starvation_count", |
- high_priority_starvation_count_); |
- state->SetInteger("immediate_starvation_count", immediate_starvation_count_); |
- state->SetInteger("num_blocked_queues_to_report", |
- num_blocked_queues_to_report_); |
-} |
- |
-void TaskQueueSelector::SetTaskQueueSelectorObserver(Observer* observer) { |
- task_queue_selector_observer_ = observer; |
-} |
- |
-bool TaskQueueSelector::EnabledWorkQueuesEmpty() const { |
- DCHECK(main_thread_checker_.CalledOnValidThread()); |
- for (TaskQueue::QueuePriority priority = TaskQueue::CONTROL_PRIORITY; |
- priority < TaskQueue::QUEUE_PRIORITY_COUNT; |
- priority = NextPriority(priority)) { |
- if (!enabled_selector_.delayed_work_queue_sets()->IsSetEmpty(priority) || |
- !enabled_selector_.immediate_work_queue_sets()->IsSetEmpty(priority)) { |
- return false; |
- } |
- } |
- return true; |
-} |
- |
-void TaskQueueSelector::SetImmediateStarvationCountForTest( |
- size_t immediate_starvation_count) { |
- immediate_starvation_count_ = immediate_starvation_count; |
-} |
- |
-} // namespace internal |
-} // namespace scheduler |