| Index: components/scheduler/base/task_queue_impl.cc
|
| diff --git a/components/scheduler/base/task_queue_impl.cc b/components/scheduler/base/task_queue_impl.cc
|
| deleted file mode 100644
|
| index 7d684fb000c3aac28cd4fa0087eedc8cbb1f1232..0000000000000000000000000000000000000000
|
| --- a/components/scheduler/base/task_queue_impl.cc
|
| +++ /dev/null
|
| @@ -1,717 +0,0 @@
|
| -// Copyright 2015 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_impl.h"
|
| -
|
| -#include "base/trace_event/blame_context.h"
|
| -#include "components/scheduler/base/task_queue_manager.h"
|
| -#include "components/scheduler/base/task_queue_manager_delegate.h"
|
| -#include "components/scheduler/base/time_domain.h"
|
| -#include "components/scheduler/base/work_queue.h"
|
| -
|
| -namespace scheduler {
|
| -namespace internal {
|
| -
|
| -TaskQueueImpl::TaskQueueImpl(
|
| - TaskQueueManager* task_queue_manager,
|
| - TimeDomain* time_domain,
|
| - const Spec& spec,
|
| - const char* disabled_by_default_tracing_category,
|
| - const char* disabled_by_default_verbose_tracing_category)
|
| - : thread_id_(base::PlatformThread::CurrentId()),
|
| - any_thread_(task_queue_manager, spec.pump_policy, time_domain),
|
| - name_(spec.name),
|
| - disabled_by_default_tracing_category_(
|
| - disabled_by_default_tracing_category),
|
| - disabled_by_default_verbose_tracing_category_(
|
| - disabled_by_default_verbose_tracing_category),
|
| - main_thread_only_(task_queue_manager,
|
| - spec.pump_policy,
|
| - this,
|
| - time_domain),
|
| - wakeup_policy_(spec.wakeup_policy),
|
| - should_monitor_quiescence_(spec.should_monitor_quiescence),
|
| - should_notify_observers_(spec.should_notify_observers),
|
| - should_report_when_execution_blocked_(
|
| - spec.should_report_when_execution_blocked) {
|
| - DCHECK(time_domain);
|
| - time_domain->RegisterQueue(this);
|
| -}
|
| -
|
| -TaskQueueImpl::~TaskQueueImpl() {
|
| -#if DCHECK_IS_ON()
|
| - base::AutoLock lock(any_thread_lock_);
|
| - // NOTE this check shouldn't fire because |TaskQueueManager::queues_|
|
| - // contains a strong reference to this TaskQueueImpl and the TaskQueueManager
|
| - // destructor calls UnregisterTaskQueue on all task queues.
|
| - DCHECK(any_thread().task_queue_manager == nullptr)
|
| - << "UnregisterTaskQueue must be called first!";
|
| -
|
| -#endif
|
| -}
|
| -
|
| -TaskQueueImpl::Task::Task()
|
| - : PendingTask(tracked_objects::Location(),
|
| - base::Closure(),
|
| - base::TimeTicks(),
|
| - true),
|
| -#ifndef NDEBUG
|
| - enqueue_order_set_(false),
|
| -#endif
|
| - enqueue_order_(0) {
|
| - sequence_num = 0;
|
| -}
|
| -
|
| -TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from,
|
| - const base::Closure& task,
|
| - base::TimeTicks desired_run_time,
|
| - EnqueueOrder sequence_number,
|
| - bool nestable)
|
| - : PendingTask(posted_from, task, desired_run_time, nestable),
|
| -#ifndef NDEBUG
|
| - enqueue_order_set_(false),
|
| -#endif
|
| - enqueue_order_(0) {
|
| - sequence_num = sequence_number;
|
| -}
|
| -
|
| -TaskQueueImpl::Task::Task(const tracked_objects::Location& posted_from,
|
| - const base::Closure& task,
|
| - base::TimeTicks desired_run_time,
|
| - EnqueueOrder sequence_number,
|
| - bool nestable,
|
| - EnqueueOrder enqueue_order)
|
| - : PendingTask(posted_from, task, desired_run_time, nestable),
|
| -#ifndef NDEBUG
|
| - enqueue_order_set_(true),
|
| -#endif
|
| - enqueue_order_(enqueue_order) {
|
| - sequence_num = sequence_number;
|
| -}
|
| -
|
| -TaskQueueImpl::AnyThread::AnyThread(TaskQueueManager* task_queue_manager,
|
| - PumpPolicy pump_policy,
|
| - TimeDomain* time_domain)
|
| - : task_queue_manager(task_queue_manager),
|
| - pump_policy(pump_policy),
|
| - time_domain(time_domain) {}
|
| -
|
| -TaskQueueImpl::AnyThread::~AnyThread() {}
|
| -
|
| -TaskQueueImpl::MainThreadOnly::MainThreadOnly(
|
| - TaskQueueManager* task_queue_manager,
|
| - PumpPolicy pump_policy,
|
| - TaskQueueImpl* task_queue,
|
| - TimeDomain* time_domain)
|
| - : task_queue_manager(task_queue_manager),
|
| - pump_policy(pump_policy),
|
| - time_domain(time_domain),
|
| - delayed_work_queue(new WorkQueue(task_queue, "delayed")),
|
| - immediate_work_queue(new WorkQueue(task_queue, "immediate")),
|
| - set_index(0),
|
| - is_enabled(true),
|
| - blame_context(nullptr) {}
|
| -
|
| -TaskQueueImpl::MainThreadOnly::~MainThreadOnly() {}
|
| -
|
| -void TaskQueueImpl::UnregisterTaskQueue() {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - if (main_thread_only().time_domain)
|
| - main_thread_only().time_domain->UnregisterQueue(this);
|
| - if (!any_thread().task_queue_manager)
|
| - return;
|
| - any_thread().time_domain = nullptr;
|
| - main_thread_only().time_domain = nullptr;
|
| - any_thread().task_queue_manager->UnregisterTaskQueue(this);
|
| -
|
| - any_thread().task_queue_manager = nullptr;
|
| - main_thread_only().task_queue_manager = nullptr;
|
| - main_thread_only().delayed_incoming_queue = std::priority_queue<Task>();
|
| - any_thread().immediate_incoming_queue = std::queue<Task>();
|
| - main_thread_only().immediate_work_queue.reset();
|
| - main_thread_only().delayed_work_queue.reset();
|
| -}
|
| -
|
| -bool TaskQueueImpl::RunsTasksOnCurrentThread() const {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - return base::PlatformThread::CurrentId() == thread_id_;
|
| -}
|
| -
|
| -bool TaskQueueImpl::PostDelayedTask(const tracked_objects::Location& from_here,
|
| - const base::Closure& task,
|
| - base::TimeDelta delay) {
|
| - if (delay.is_zero())
|
| - return PostImmediateTaskImpl(from_here, task, TaskType::NORMAL);
|
| -
|
| - return PostDelayedTaskImpl(from_here, task, delay, TaskType::NORMAL);
|
| -}
|
| -
|
| -bool TaskQueueImpl::PostNonNestableDelayedTask(
|
| - const tracked_objects::Location& from_here,
|
| - const base::Closure& task,
|
| - base::TimeDelta delay) {
|
| - if (delay.is_zero())
|
| - return PostImmediateTaskImpl(from_here, task, TaskType::NON_NESTABLE);
|
| -
|
| - return PostDelayedTaskImpl(from_here, task, delay, TaskType::NON_NESTABLE);
|
| -}
|
| -
|
| -bool TaskQueueImpl::PostImmediateTaskImpl(
|
| - const tracked_objects::Location& from_here,
|
| - const base::Closure& task,
|
| - TaskType task_type) {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - if (!any_thread().task_queue_manager)
|
| - return false;
|
| -
|
| - EnqueueOrder sequence_number =
|
| - any_thread().task_queue_manager->GetNextSequenceNumber();
|
| -
|
| - PushOntoImmediateIncomingQueueLocked(
|
| - Task(from_here, task, base::TimeTicks(), sequence_number,
|
| - task_type != TaskType::NON_NESTABLE, sequence_number));
|
| - return true;
|
| -}
|
| -
|
| -bool TaskQueueImpl::PostDelayedTaskImpl(
|
| - const tracked_objects::Location& from_here,
|
| - const base::Closure& task,
|
| - base::TimeDelta delay,
|
| - TaskType task_type) {
|
| - DCHECK_GT(delay, base::TimeDelta());
|
| - if (base::PlatformThread::CurrentId() == thread_id_) {
|
| - // Lock-free fast path for delayed tasks posted from the main thread.
|
| - if (!main_thread_only().task_queue_manager)
|
| - return false;
|
| -
|
| - EnqueueOrder sequence_number =
|
| - main_thread_only().task_queue_manager->GetNextSequenceNumber();
|
| -
|
| - base::TimeTicks time_domain_now = main_thread_only().time_domain->Now();
|
| - base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
|
| - PushOntoDelayedIncomingQueueFromMainThread(
|
| - Task(from_here, task, time_domain_delayed_run_time, sequence_number,
|
| - task_type != TaskType::NON_NESTABLE),
|
| - time_domain_now);
|
| - } else {
|
| - // NOTE posting a delayed task from a different thread is not expected to
|
| - // be common. This pathway is less optimal than perhaps it could be
|
| - // because it causes two main thread tasks to be run. Should this
|
| - // assumption prove to be false in future, we may need to revisit this.
|
| - base::AutoLock lock(any_thread_lock_);
|
| - if (!any_thread().task_queue_manager)
|
| - return false;
|
| -
|
| - EnqueueOrder sequence_number =
|
| - any_thread().task_queue_manager->GetNextSequenceNumber();
|
| -
|
| - base::TimeTicks time_domain_now = any_thread().time_domain->Now();
|
| - base::TimeTicks time_domain_delayed_run_time = time_domain_now + delay;
|
| - PushOntoDelayedIncomingQueueLocked(
|
| - Task(from_here, task, time_domain_delayed_run_time, sequence_number,
|
| - task_type != TaskType::NON_NESTABLE));
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
|
| - Task pending_task,
|
| - base::TimeTicks now) {
|
| - main_thread_only().task_queue_manager->DidQueueTask(pending_task);
|
| -
|
| - // Schedule a later call to MoveReadyDelayedTasksToDelayedWorkQueue.
|
| - base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
|
| - main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
|
| - main_thread_only().time_domain->ScheduleDelayedWork(
|
| - this, delayed_run_time, now);
|
| - TraceQueueSize(false);
|
| -}
|
| -
|
| -void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
|
| - any_thread().task_queue_manager->DidQueueTask(pending_task);
|
| -
|
| - int thread_hop_task_sequence_number =
|
| - any_thread().task_queue_manager->GetNextSequenceNumber();
|
| - PushOntoImmediateIncomingQueueLocked(Task(
|
| - FROM_HERE,
|
| - base::Bind(&TaskQueueImpl::ScheduleDelayedWorkTask, this,
|
| - base::Passed(&pending_task)),
|
| - base::TimeTicks(), thread_hop_task_sequence_number, false,
|
| - thread_hop_task_sequence_number));
|
| -}
|
| -
|
| -void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task pending_task) {
|
| - if (any_thread().immediate_incoming_queue.empty())
|
| - any_thread().time_domain->RegisterAsUpdatableTaskQueue(this);
|
| - if (any_thread().pump_policy == PumpPolicy::AUTO &&
|
| - any_thread().immediate_incoming_queue.empty()) {
|
| - any_thread().task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
|
| - }
|
| - any_thread().task_queue_manager->DidQueueTask(pending_task);
|
| - any_thread().immediate_incoming_queue.push(std::move(pending_task));
|
| - TraceQueueSize(true);
|
| -}
|
| -
|
| -void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
|
| - DCHECK(main_thread_checker_.CalledOnValidThread());
|
| - base::TimeTicks delayed_run_time = pending_task.delayed_run_time;
|
| - main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
|
| - main_thread_only().time_domain->ScheduleDelayedWork(
|
| - this, delayed_run_time,
|
| - main_thread_only().time_domain->Now());
|
| -}
|
| -
|
| -void TaskQueueImpl::SetQueueEnabled(bool enabled) {
|
| - if (main_thread_only().is_enabled == enabled)
|
| - return;
|
| - main_thread_only().is_enabled = enabled;
|
| - if (!main_thread_only().task_queue_manager)
|
| - return;
|
| - if (enabled) {
|
| - main_thread_only().task_queue_manager->selector_.EnableQueue(this);
|
| - } else {
|
| - main_thread_only().task_queue_manager->selector_.DisableQueue(this);
|
| - }
|
| -}
|
| -
|
| -bool TaskQueueImpl::IsQueueEnabled() const {
|
| - return main_thread_only().is_enabled;
|
| -}
|
| -
|
| -bool TaskQueueImpl::IsEmpty() const {
|
| - if (!main_thread_only().delayed_work_queue->Empty() ||
|
| - !main_thread_only().immediate_work_queue->Empty()) {
|
| - return false;
|
| - }
|
| -
|
| - base::AutoLock lock(any_thread_lock_);
|
| - return any_thread().immediate_incoming_queue.empty() &&
|
| - main_thread_only().delayed_incoming_queue.empty();
|
| -}
|
| -
|
| -bool TaskQueueImpl::HasPendingImmediateWork() const {
|
| - if (!main_thread_only().delayed_work_queue->Empty() ||
|
| - !main_thread_only().immediate_work_queue->Empty()) {
|
| - return true;
|
| - }
|
| -
|
| - return NeedsPumping();
|
| -}
|
| -
|
| -bool TaskQueueImpl::NeedsPumping() const {
|
| - if (!main_thread_only().immediate_work_queue->Empty())
|
| - return false;
|
| -
|
| - base::AutoLock lock(any_thread_lock_);
|
| - if (!any_thread().immediate_incoming_queue.empty())
|
| - return true;
|
| -
|
| - // If there's no immediate Incoming work then we only need pumping if there
|
| - // is a delayed task that should be running now.
|
| - if (main_thread_only().delayed_incoming_queue.empty())
|
| - return false;
|
| -
|
| - return main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
|
| - main_thread_only().time_domain->CreateLazyNow().Now();
|
| -}
|
| -
|
| -bool TaskQueueImpl::TaskIsOlderThanQueuedImmediateTasksLocked(
|
| - const Task* task) {
|
| - // A null task is passed when UpdateQueue is called before any task is run.
|
| - // In this case we don't want to pump an after_wakeup queue, so return true
|
| - // here.
|
| - if (!task)
|
| - return true;
|
| -
|
| - // Return false if task is newer than the oldest immediate task.
|
| - if (!any_thread().immediate_incoming_queue.empty() &&
|
| - task->enqueue_order() >
|
| - any_thread().immediate_incoming_queue.front().enqueue_order()) {
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -bool TaskQueueImpl::TaskIsOlderThanQueuedDelayedTasks(const Task* task) {
|
| - DCHECK(main_thread_checker_.CalledOnValidThread());
|
| - // A null task is passed when UpdateQueue is called before any task is run.
|
| - // In this case we don't want to pump an after_wakeup queue, so return true
|
| - // here.
|
| - if (!task)
|
| - return true;
|
| -
|
| - EnqueueOrder enqueue_order;
|
| - if (!main_thread_only().delayed_work_queue->GetFrontTaskEnqueueOrder(
|
| - &enqueue_order)) {
|
| - return true;
|
| - }
|
| -
|
| - return task->enqueue_order() < enqueue_order;
|
| -}
|
| -
|
| -bool TaskQueueImpl::ShouldAutoPumpImmediateQueueLocked(
|
| - bool should_trigger_wakeup,
|
| - const Task* previous_task) {
|
| - if (main_thread_only().pump_policy == PumpPolicy::MANUAL)
|
| - return false;
|
| - if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP &&
|
| - (!should_trigger_wakeup ||
|
| - TaskIsOlderThanQueuedImmediateTasksLocked(previous_task)))
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -bool TaskQueueImpl::ShouldAutoPumpDelayedQueue(bool should_trigger_wakeup,
|
| - const Task* previous_task) {
|
| - if (main_thread_only().pump_policy == PumpPolicy::MANUAL)
|
| - return false;
|
| - if (main_thread_only().pump_policy == PumpPolicy::AFTER_WAKEUP &&
|
| - (!should_trigger_wakeup ||
|
| - TaskIsOlderThanQueuedDelayedTasks(previous_task)))
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -void TaskQueueImpl::MoveReadyDelayedTasksToDelayedWorkQueue(LazyNow* lazy_now) {
|
| - // Enqueue all delayed tasks that should be running now.
|
| - while (!main_thread_only().delayed_incoming_queue.empty() &&
|
| - main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
|
| - lazy_now->Now()) {
|
| - // Note: the const_cast is needed because there is no direct way to move
|
| - // elements out of a priority queue. The queue must not be modified between
|
| - // the top() and the pop().
|
| - main_thread_only().delayed_work_queue->PushAndSetEnqueueOrder(
|
| - std::move(
|
| - const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())),
|
| - main_thread_only().task_queue_manager->GetNextSequenceNumber());
|
| - main_thread_only().delayed_incoming_queue.pop();
|
| - }
|
| -}
|
| -
|
| -void TaskQueueImpl::UpdateDelayedWorkQueue(LazyNow* lazy_now,
|
| - bool should_trigger_wakeup,
|
| - const Task* previous_task) {
|
| - if (!main_thread_only().task_queue_manager)
|
| - return;
|
| - if (!ShouldAutoPumpDelayedQueue(should_trigger_wakeup, previous_task))
|
| - return;
|
| - MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
|
| - TraceQueueSize(false);
|
| -}
|
| -
|
| -void TaskQueueImpl::UpdateImmediateWorkQueue(bool should_trigger_wakeup,
|
| - const Task* previous_task) {
|
| - DCHECK(main_thread_only().immediate_work_queue->Empty());
|
| - base::AutoLock lock(any_thread_lock_);
|
| - if (!main_thread_only().task_queue_manager)
|
| - return;
|
| - if (!ShouldAutoPumpImmediateQueueLocked(should_trigger_wakeup, previous_task))
|
| - return;
|
| -
|
| - main_thread_only().immediate_work_queue->SwapLocked(
|
| - any_thread().immediate_incoming_queue);
|
| -
|
| - // |any_thread().immediate_incoming_queue| is now empty so
|
| - // TimeDomain::UpdateQueues no longer needs to consider this queue for
|
| - // reloading.
|
| - main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
|
| -}
|
| -
|
| -void TaskQueueImpl::TraceQueueSize(bool is_locked) const {
|
| - bool is_tracing;
|
| - TRACE_EVENT_CATEGORY_GROUP_ENABLED(disabled_by_default_tracing_category_,
|
| - &is_tracing);
|
| - if (!is_tracing)
|
| - return;
|
| -
|
| - // It's only safe to access the work queues from the main thread.
|
| - // TODO(alexclarke): We should find another way of tracing this
|
| - if (base::PlatformThread::CurrentId() != thread_id_)
|
| - return;
|
| -
|
| - if (!is_locked)
|
| - any_thread_lock_.Acquire();
|
| - else
|
| - any_thread_lock_.AssertAcquired();
|
| - TRACE_COUNTER1(disabled_by_default_tracing_category_, GetName(),
|
| - any_thread().immediate_incoming_queue.size() +
|
| - main_thread_only().immediate_work_queue->Size() +
|
| - main_thread_only().delayed_work_queue->Size() +
|
| - main_thread_only().delayed_incoming_queue.size());
|
| - if (!is_locked)
|
| - any_thread_lock_.Release();
|
| -}
|
| -
|
| -void TaskQueueImpl::SetPumpPolicy(PumpPolicy pump_policy) {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - if (pump_policy == PumpPolicy::AUTO &&
|
| - any_thread().pump_policy != PumpPolicy::AUTO) {
|
| - LazyNow lazy_now(main_thread_only().time_domain->CreateLazyNow());
|
| - PumpQueueLocked(&lazy_now, true);
|
| - }
|
| - any_thread().pump_policy = pump_policy;
|
| - main_thread_only().pump_policy = pump_policy;
|
| -}
|
| -
|
| -TaskQueue::PumpPolicy TaskQueueImpl::GetPumpPolicy() const {
|
| - return main_thread_only().pump_policy;
|
| -}
|
| -
|
| -void TaskQueueImpl::PumpQueueLocked(LazyNow* lazy_now, bool may_post_dowork) {
|
| - TRACE_EVENT1(disabled_by_default_tracing_category_,
|
| - "TaskQueueImpl::PumpQueueLocked", "queue", name_);
|
| - TaskQueueManager* task_queue_manager = any_thread().task_queue_manager;
|
| - if (!task_queue_manager)
|
| - return;
|
| -
|
| - MoveReadyDelayedTasksToDelayedWorkQueue(lazy_now);
|
| -
|
| - while (!any_thread().immediate_incoming_queue.empty()) {
|
| - main_thread_only().immediate_work_queue->Push(
|
| - std::move(any_thread().immediate_incoming_queue.front()));
|
| - any_thread().immediate_incoming_queue.pop();
|
| - }
|
| -
|
| - // |immediate_incoming_queue| is now empty so TimeDomain::UpdateQueues no
|
| - // longer needs to consider this queue for reloading.
|
| - main_thread_only().time_domain->UnregisterAsUpdatableTaskQueue(this);
|
| -
|
| - if (main_thread_only().immediate_work_queue->Empty() &&
|
| - main_thread_only().delayed_work_queue->Empty()) {
|
| - return;
|
| - }
|
| -
|
| - if (may_post_dowork)
|
| - task_queue_manager->MaybeScheduleImmediateWork(FROM_HERE);
|
| -}
|
| -
|
| -void TaskQueueImpl::PumpQueue(LazyNow* lazy_now, bool may_post_dowork) {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - PumpQueueLocked(lazy_now, may_post_dowork);
|
| -}
|
| -
|
| -const char* TaskQueueImpl::GetName() const {
|
| - return name_;
|
| -}
|
| -
|
| -void TaskQueueImpl::SetQueuePriority(QueuePriority priority) {
|
| - if (!main_thread_only().task_queue_manager || priority == GetQueuePriority())
|
| - return;
|
| - main_thread_only().task_queue_manager->selector_.SetQueuePriority(this,
|
| - priority);
|
| -}
|
| -
|
| -TaskQueueImpl::QueuePriority TaskQueueImpl::GetQueuePriority() const {
|
| - size_t set_index = immediate_work_queue()->work_queue_set_index();
|
| - DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index());
|
| - return static_cast<TaskQueue::QueuePriority>(set_index);
|
| -}
|
| -
|
| -// static
|
| -const char* TaskQueueImpl::PumpPolicyToString(
|
| - TaskQueue::PumpPolicy pump_policy) {
|
| - switch (pump_policy) {
|
| - case TaskQueue::PumpPolicy::AUTO:
|
| - return "auto";
|
| - case TaskQueue::PumpPolicy::AFTER_WAKEUP:
|
| - return "after_wakeup";
|
| - case TaskQueue::PumpPolicy::MANUAL:
|
| - return "manual";
|
| - default:
|
| - NOTREACHED();
|
| - return nullptr;
|
| - }
|
| -}
|
| -
|
| -// static
|
| -const char* TaskQueueImpl::WakeupPolicyToString(
|
| - TaskQueue::WakeupPolicy wakeup_policy) {
|
| - switch (wakeup_policy) {
|
| - case TaskQueue::WakeupPolicy::CAN_WAKE_OTHER_QUEUES:
|
| - return "can_wake_other_queues";
|
| - case TaskQueue::WakeupPolicy::DONT_WAKE_OTHER_QUEUES:
|
| - return "dont_wake_other_queues";
|
| - default:
|
| - NOTREACHED();
|
| - return nullptr;
|
| - }
|
| -}
|
| -
|
| -// static
|
| -const char* TaskQueueImpl::PriorityToString(QueuePriority priority) {
|
| - switch (priority) {
|
| - case CONTROL_PRIORITY:
|
| - return "control";
|
| - case HIGH_PRIORITY:
|
| - return "high";
|
| - case NORMAL_PRIORITY:
|
| - return "normal";
|
| - case BEST_EFFORT_PRIORITY:
|
| - return "best_effort";
|
| - default:
|
| - NOTREACHED();
|
| - return nullptr;
|
| - }
|
| -}
|
| -
|
| -void TaskQueueImpl::AsValueInto(base::trace_event::TracedValue* state) const {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - state->BeginDictionary();
|
| - state->SetString("name", GetName());
|
| - state->SetBoolean("enabled", main_thread_only().is_enabled);
|
| - state->SetString("time_domain_name",
|
| - main_thread_only().time_domain->GetName());
|
| - state->SetString("pump_policy", PumpPolicyToString(any_thread().pump_policy));
|
| - state->SetString("wakeup_policy", WakeupPolicyToString(wakeup_policy_));
|
| - bool verbose_tracing_enabled = false;
|
| - TRACE_EVENT_CATEGORY_GROUP_ENABLED(
|
| - disabled_by_default_verbose_tracing_category_, &verbose_tracing_enabled);
|
| - state->SetInteger("immediate_incoming_queue_size",
|
| - any_thread().immediate_incoming_queue.size());
|
| - state->SetInteger("delayed_incoming_queue_size",
|
| - main_thread_only().delayed_incoming_queue.size());
|
| - state->SetInteger("immediate_work_queue_size",
|
| - main_thread_only().immediate_work_queue->Size());
|
| - state->SetInteger("delayed_work_queue_size",
|
| - main_thread_only().delayed_work_queue->Size());
|
| - if (!main_thread_only().delayed_incoming_queue.empty()) {
|
| - base::TimeDelta delay_to_next_task =
|
| - (main_thread_only().delayed_incoming_queue.top().delayed_run_time -
|
| - main_thread_only().time_domain->CreateLazyNow().Now());
|
| - state->SetDouble("delay_to_next_task_ms",
|
| - delay_to_next_task.InMillisecondsF());
|
| - }
|
| - if (verbose_tracing_enabled) {
|
| - state->BeginArray("immediate_incoming_queue");
|
| - QueueAsValueInto(any_thread().immediate_incoming_queue, state);
|
| - state->EndArray();
|
| - state->BeginArray("delayed_work_queue");
|
| - main_thread_only().delayed_work_queue->AsValueInto(state);
|
| - state->EndArray();
|
| - state->BeginArray("immediate_work_queue");
|
| - main_thread_only().immediate_work_queue->AsValueInto(state);
|
| - state->EndArray();
|
| - state->BeginArray("delayed_incoming_queue");
|
| - QueueAsValueInto(main_thread_only().delayed_incoming_queue, state);
|
| - state->EndArray();
|
| - }
|
| - state->SetString("priority", PriorityToString(GetQueuePriority()));
|
| - state->EndDictionary();
|
| -}
|
| -
|
| -void TaskQueueImpl::AddTaskObserver(
|
| - base::MessageLoop::TaskObserver* task_observer) {
|
| - main_thread_only().task_observers.AddObserver(task_observer);
|
| -}
|
| -
|
| -void TaskQueueImpl::RemoveTaskObserver(
|
| - base::MessageLoop::TaskObserver* task_observer) {
|
| - main_thread_only().task_observers.RemoveObserver(task_observer);
|
| -}
|
| -
|
| -void TaskQueueImpl::NotifyWillProcessTask(
|
| - const base::PendingTask& pending_task) {
|
| - DCHECK(should_notify_observers_);
|
| - if (main_thread_only().blame_context)
|
| - main_thread_only().blame_context->Enter();
|
| - FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver,
|
| - main_thread_only().task_observers,
|
| - WillProcessTask(pending_task));
|
| -}
|
| -
|
| -void TaskQueueImpl::NotifyDidProcessTask(
|
| - const base::PendingTask& pending_task) {
|
| - DCHECK(should_notify_observers_);
|
| - FOR_EACH_OBSERVER(base::MessageLoop::TaskObserver,
|
| - main_thread_only().task_observers,
|
| - DidProcessTask(pending_task));
|
| - if (main_thread_only().blame_context)
|
| - main_thread_only().blame_context->Leave();
|
| -}
|
| -
|
| -void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) {
|
| - base::AutoLock lock(any_thread_lock_);
|
| - DCHECK(time_domain);
|
| - // NOTE this is similar to checking |any_thread().task_queue_manager| but the
|
| - // TaskQueueSelectorTests constructs TaskQueueImpl directly with a null
|
| - // task_queue_manager. Instead we check |any_thread().time_domain| which is
|
| - // another way of asserting that UnregisterTaskQueue has not been called.
|
| - DCHECK(any_thread().time_domain);
|
| - if (!any_thread().time_domain)
|
| - return;
|
| - DCHECK(main_thread_checker_.CalledOnValidThread());
|
| - if (time_domain == main_thread_only().time_domain)
|
| - return;
|
| -
|
| - main_thread_only().time_domain->MigrateQueue(this, time_domain);
|
| - main_thread_only().time_domain = time_domain;
|
| - any_thread().time_domain = time_domain;
|
| -}
|
| -
|
| -TimeDomain* TaskQueueImpl::GetTimeDomain() const {
|
| - if (base::PlatformThread::CurrentId() == thread_id_)
|
| - return main_thread_only().time_domain;
|
| -
|
| - base::AutoLock lock(any_thread_lock_);
|
| - return any_thread().time_domain;
|
| -}
|
| -
|
| -void TaskQueueImpl::SetBlameContext(
|
| - base::trace_event::BlameContext* blame_context) {
|
| - main_thread_only().blame_context = blame_context;
|
| -}
|
| -
|
| -// static
|
| -void TaskQueueImpl::QueueAsValueInto(const std::queue<Task>& queue,
|
| - base::trace_event::TracedValue* state) {
|
| - // Remove const to search |queue| in the destructive manner. Restore the
|
| - // content from |visited| later.
|
| - std::queue<Task>* mutable_queue = const_cast<std::queue<Task>*>(&queue);
|
| - std::queue<Task> visited;
|
| - while (!mutable_queue->empty()) {
|
| - TaskAsValueInto(mutable_queue->front(), state);
|
| - visited.push(std::move(mutable_queue->front()));
|
| - mutable_queue->pop();
|
| - }
|
| - *mutable_queue = std::move(visited);
|
| -}
|
| -
|
| -// static
|
| -void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue,
|
| - base::trace_event::TracedValue* state) {
|
| - // Remove const to search |queue| in the destructive manner. Restore the
|
| - // content from |visited| later.
|
| - std::priority_queue<Task>* mutable_queue =
|
| - const_cast<std::priority_queue<Task>*>(&queue);
|
| - std::priority_queue<Task> visited;
|
| - while (!mutable_queue->empty()) {
|
| - TaskAsValueInto(mutable_queue->top(), state);
|
| - visited.push(std::move(const_cast<Task&>(mutable_queue->top())));
|
| - mutable_queue->pop();
|
| - }
|
| - *mutable_queue = std::move(visited);
|
| -}
|
| -
|
| -// static
|
| -void TaskQueueImpl::TaskAsValueInto(const Task& task,
|
| - base::trace_event::TracedValue* state) {
|
| - state->BeginDictionary();
|
| - state->SetString("posted_from", task.posted_from.ToString());
|
| -#ifndef NDEBUG
|
| - if (task.enqueue_order_set())
|
| - state->SetInteger("enqueue_order", task.enqueue_order());
|
| -#else
|
| - state->SetInteger("enqueue_order", task.enqueue_order());
|
| -#endif
|
| - state->SetInteger("sequence_num", task.sequence_num);
|
| - state->SetBoolean("nestable", task.nestable);
|
| - state->SetBoolean("is_high_res", task.is_high_res);
|
| - state->SetDouble(
|
| - "delayed_run_time",
|
| - (task.delayed_run_time - base::TimeTicks()).InMicroseconds() / 1000.0L);
|
| - state->EndDictionary();
|
| -}
|
| -
|
| -} // namespace internal
|
| -} // namespace scheduler
|
|
|