blob: 5c81ebefd7f828f23a02b8704337265e4b616ebd [file] [log] [blame]
// Copyright 2019 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.
#ifndef CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_
#define CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_
#include <array>
#include "base/memory/scoped_refptr.h"
#include "base/task/sequence_manager/task_queue.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
namespace base {
namespace sequence_manager {
class SequenceManager;
class TimeDomain;
} // namespace sequence_manager
} // namespace base
namespace content {
// Common task queues for browser threads. This class holds all the queues
// needed by browser threads. This makes it easy for all browser threads to have
// the same queues. Thic class also provides a Handler to act on the queues from
// any thread.
//
// Instances must be created and destroyed on the same thread as the
// underlying SequenceManager and instances are not allowed to outlive this
// SequenceManager. All methods of this class must be called from the
// associated thread unless noted otherwise. If you need to perform operations
// from a different thread use the a Handle instance instead.
//
// Attention: All queues are initially disabled, that is, tasks will not be run
// for them.
class CONTENT_EXPORT BrowserTaskQueues {
public:
enum class QueueType {
// Catch all for tasks that don't fit other categories.
// TODO(alexclarke): Introduce new semantic types as needed to minimize the
// number of default tasks.
kDefault,
// For non-urgent work, that will only execute if there's nothing else to
// do. Can theoretically be starved indefinitely although that's unlikely in
// practice.
kBestEffort,
// For tasks on the critical path up to issuing the initial navigation.
kBootstrap,
// For navigation and preconnection related tasks.
kNavigationAndPreconnection,
// A generic high priority queue. Long term we should replace this with
// additional semantic annotations.
kUserBlocking,
kMaxValue = kUserBlocking
};
static constexpr size_t kNumQueueTypes =
static_cast<size_t>(QueueType::kMaxValue) + 1;
// Handle to a BrowserTaskQueues instance that can be used from any thread
// as all operations are thread safe.
//
// If the underlying BrowserTaskQueues is destroyed all methods of this
// class become no-ops, that is it is safe for this class to outlive its
// parent BrowserTaskQueues.
class CONTENT_EXPORT Handle {
public:
// Handles can be copied / moved around.
Handle(Handle&&) noexcept;
Handle(const Handle&);
~Handle();
Handle& operator=(Handle&&) noexcept;
Handle& operator=(const Handle&);
// Returns the task runner that should be returned by
// ThreadTaskRunnerHandle::Get().
const scoped_refptr<base::SingleThreadTaskRunner>& GetDefaultTaskRunner() {
return default_task_runner_;
}
const scoped_refptr<base::SingleThreadTaskRunner>& GetBrowserTaskRunner(
QueueType queue_type) const {
return browser_task_runners_[static_cast<size_t>(queue_type)];
}
// Initializes any scheduler experiments. Should be called after
// FeatureLists have been initialized (which usually happens after task
// queues are set up).
void PostFeatureListInitializationSetup();
// Enables all tasks queues. Can be called multiple times.
void EnableAllQueues();
// Enables all task queues except the effort ones. Can be called multiple
// times.
void EnableAllExceptBestEffortQueues();
// Schedules |on_pending_task_ran| to run when all pending tasks (at the
// time this method was invoked) have run. Only "runnable" tasks are taken
// into account, that is tasks from disabled queues are ignored, also this
// only works reliably for immediate tasks, delayed tasks might or might not
// run depending on timing.
//
// The callback will run on the thread associated with this Handle, unless
// that thread is no longer accepting tasks; in which case it will be run
// inline immediately.
//
// The recommended usage pattern is:
// RunLoop run_loop;
// handle.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
// run_loop.Run();
void ScheduleRunAllPendingTasksForTesting(
base::OnceClosure on_pending_task_ran);
private:
// Only BrowserTaskQueues can create new instances
friend class BrowserTaskQueues;
explicit Handle(BrowserTaskQueues* task_queues);
// |outer_| can only be safely used from a task posted to one of the
// runners.
BrowserTaskQueues* outer_ = nullptr;
scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
browser_task_runners_;
};
// |sequence_manager| and |time_domain| must outlive this instance.
explicit BrowserTaskQueues(
BrowserThread::ID thread_id,
base::sequence_manager::SequenceManager* sequence_manager,
base::sequence_manager::TimeDomain* time_domain);
// Destroys all queues.
~BrowserTaskQueues();
Handle CreateHandle() { return Handle(this); }
private:
// All these methods can only be called from the associated thread. To make
// sure that is the case they will always be called from a task posted to the
// |control_queue_|.
void StartRunAllPendingTasksForTesting(
base::ScopedClosureRunner on_pending_task_ran);
void EndRunAllPendingTasksForTesting(
base::ScopedClosureRunner on_pending_task_ran);
void EnableAllQueues();
void EnableAllExceptBestEffortQueues();
void PostFeatureListInitializationSetup();
base::sequence_manager::TaskQueue* GetBrowserTaskQueue(QueueType type) const {
return browser_queues_and_voters_[static_cast<size_t>(type)].first.get();
}
std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
CreateBrowserTaskRunners() const;
using QueueVoterPair = std::pair<
scoped_refptr<base::sequence_manager::TaskQueue>,
std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>>;
std::array<QueueVoterPair, kNumQueueTypes> browser_queues_and_voters_;
// Helper queue to make sure private methods run on the associated thread. the
// control queue has maximum priority and will never be disabled.
scoped_refptr<base::sequence_manager::TaskQueue> control_queue_;
// Queue that backs the default TaskRunner registered with SequenceManager.
// This will be the one returned by ThreadTaskRunnerHandle::Get(). Note this
// is different from QueueType:kDefault as this queue needs to be enabled from
// the beginning.
scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
// Helper queue to run all pending tasks.
scoped_refptr<base::sequence_manager::TaskQueue> run_all_pending_tasks_queue_;
int run_all_pending_nesting_level_ = 0;
};
} // namespace content
#endif // CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_