| 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
|
| index 312023246048d50d30a1c2285073c9da8cb78676..9db8ab9c2de43124bb2b04565a02beb9d256a06a 100644
|
| --- a/components/scheduler/base/task_queue_selector.cc
|
| +++ b/components/scheduler/base/task_queue_selector.cc
|
| @@ -13,8 +13,8 @@ namespace scheduler {
|
| namespace internal {
|
|
|
| TaskQueueSelector::TaskQueueSelector()
|
| - : enabled_selector_(this),
|
| - blocked_selector_(this),
|
| + : enabled_selector_(this, "enabled"),
|
| + blocked_selector_(this, "blocked"),
|
| immediate_starvation_count_(0),
|
| high_priority_starvation_count_(0),
|
| num_blocked_queues_to_report_(0),
|
| @@ -25,17 +25,25 @@ TaskQueueSelector::~TaskQueueSelector() {}
|
| void TaskQueueSelector::AddQueue(internal::TaskQueueImpl* queue) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| DCHECK(queue->IsQueueEnabled());
|
| - SetQueuePriority(queue, TaskQueue::NORMAL_PRIORITY);
|
| + 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
|
| }
|
| }
|
|
|
| @@ -45,9 +53,9 @@ void TaskQueueSelector::EnableQueue(internal::TaskQueueImpl* queue) {
|
| if (queue->should_report_when_execution_blocked()) {
|
| DCHECK_GT(num_blocked_queues_to_report_, 0u);
|
| num_blocked_queues_to_report_--;
|
| + blocked_selector_.RemoveQueue(queue);
|
| }
|
| - blocked_selector_.RemoveQueue(queue);
|
| - enabled_selector_.AssignQueueToSet(queue, queue->GetQueuePriority());
|
| + enabled_selector_.AddQueue(queue, queue->GetQueuePriority());
|
| if (task_queue_selector_observer_)
|
| task_queue_selector_observer_->OnTaskQueueEnabled(queue);
|
| }
|
| @@ -56,9 +64,10 @@ void TaskQueueSelector::DisableQueue(internal::TaskQueueImpl* queue) {
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| DCHECK(!queue->IsQueueEnabled());
|
| enabled_selector_.RemoveQueue(queue);
|
| - blocked_selector_.AssignQueueToSet(queue, queue->GetQueuePriority());
|
| - if (queue->should_report_when_execution_blocked())
|
| + if (queue->should_report_when_execution_blocked()) {
|
| + blocked_selector_.AddQueue(queue, queue->GetQueuePriority());
|
| num_blocked_queues_to_report_++;
|
| + }
|
| }
|
|
|
| void TaskQueueSelector::SetQueuePriority(internal::TaskQueueImpl* queue,
|
| @@ -66,9 +75,15 @@ void TaskQueueSelector::SetQueuePriority(internal::TaskQueueImpl* queue,
|
| DCHECK_LT(priority, TaskQueue::QUEUE_PRIORITY_COUNT);
|
| DCHECK(main_thread_checker_.CalledOnValidThread());
|
| if (queue->IsQueueEnabled()) {
|
| - enabled_selector_.AssignQueueToSet(queue, priority);
|
| + enabled_selector_.ChangeSetIndex(queue, priority);
|
| + } else if (queue->should_report_when_execution_blocked()) {
|
| + blocked_selector_.ChangeSetIndex(queue, priority);
|
| } else {
|
| - blocked_selector_.AssignQueueToSet(queue, priority);
|
| + // 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());
|
| }
|
| @@ -80,50 +95,50 @@ TaskQueue::QueuePriority TaskQueueSelector::NextPriority(
|
| }
|
|
|
| TaskQueueSelector::PrioritizingSelector::PrioritizingSelector(
|
| - TaskQueueSelector* task_queue_selector)
|
| + TaskQueueSelector* task_queue_selector,
|
| + const char* name)
|
| : task_queue_selector_(task_queue_selector),
|
| - delayed_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT),
|
| - immediate_work_queue_sets_(TaskQueue::QUEUE_PRIORITY_COUNT) {}
|
| + 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::AssignQueueToSet(
|
| +void TaskQueueSelector::PrioritizingSelector::ChangeSetIndex(
|
| internal::TaskQueueImpl* queue,
|
| TaskQueue::QueuePriority priority) {
|
| - delayed_work_queue_sets_.AssignQueueToSet(queue->delayed_work_queue(),
|
| +#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);
|
| - immediate_work_queue_sets_.AssignQueueToSet(queue->immediate_work_queue(),
|
| - priority);
|
| - // The #if DCHECK_IS_ON() shouldn't be necessary but this doesn't compile on
|
| - // chromeos bots without it :(
|
| #if DCHECK_IS_ON()
|
| - DCHECK_EQ(queue->delayed_work_queue()->Empty(),
|
| - !delayed_work_queue_sets_.ContainsWorkQueueForTest(
|
| - queue->delayed_work_queue()));
|
| - DCHECK_EQ(queue->immediate_work_queue()->Empty(),
|
| - !immediate_work_queue_sets_.ContainsWorkQueueForTest(
|
| - queue->immediate_work_queue()));
|
| + DCHECK(CheckContainsQueueForTest(queue));
|
| #endif
|
| }
|
|
|
| void TaskQueueSelector::PrioritizingSelector::RemoveQueue(
|
| internal::TaskQueueImpl* queue) {
|
| #if DCHECK_IS_ON()
|
| - DCHECK_EQ(queue->delayed_work_queue()->Empty(),
|
| - !delayed_work_queue_sets_.ContainsWorkQueueForTest(
|
| - queue->delayed_work_queue()))
|
| - << " Did you try to RemoveQueue twice? Thats not supported!";
|
| - DCHECK_EQ(queue->immediate_work_queue()->Empty(),
|
| - !immediate_work_queue_sets_.ContainsWorkQueueForTest(
|
| - queue->immediate_work_queue()))
|
| - << " Did you try to RemoveQueue twice? Thats not supported!";
|
| + 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(!delayed_work_queue_sets_.ContainsWorkQueueForTest(
|
| - queue->delayed_work_queue()));
|
| - DCHECK(!immediate_work_queue_sets_.ContainsWorkQueueForTest(
|
| - queue->delayed_work_queue()));
|
| + DCHECK(!CheckContainsQueueForTest(queue));
|
| #endif
|
| }
|
|
|
| @@ -220,6 +235,23 @@ bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService(
|
| 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;
|
| @@ -239,6 +271,7 @@ bool TaskQueueSelector::SelectWorkQueueToService(WorkQueue** out_work_queue) {
|
| }
|
|
|
| void TaskQueueSelector::TrySelectingBlockedQueue() {
|
| + DCHECK(main_thread_checker_.CalledOnValidThread());
|
| if (!num_blocked_queues_to_report_ || !task_queue_selector_observer_)
|
| return;
|
| WorkQueue* chosen_blocked_queue;
|
| @@ -255,6 +288,7 @@ void TaskQueueSelector::TrySelectingBlockedQueue() {
|
|
|
| void TaskQueueSelector::TrySelectingBlockedQueueOverEnabledQueue(
|
| const WorkQueue& chosen_enabled_queue) {
|
| + DCHECK(main_thread_checker_.CalledOnValidThread());
|
| if (!num_blocked_queues_to_report_ || !task_queue_selector_observer_)
|
| return;
|
|
|
| @@ -325,6 +359,7 @@ void TaskQueueSelector::SetTaskQueueSelectorObserver(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)) {
|
|
|