blob: 03c06dcaba2bed6a0ec7cf3b0df8e5a2eedb3529 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2019 The Chromium Authors
Carlos Caballero5f6212b2019-05-13 13:45:162// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_
6#define CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_
7
8#include <array>
9
Avi Drissmanadac21992023-01-11 23:46:3910#include "base/functional/callback_helpers.h"
Keishi Hattori0e45c022021-11-27 09:25:5211#include "base/memory/raw_ptr.h"
Carlos Caballero5f6212b2019-05-13 13:45:1612#include "base/memory/scoped_refptr.h"
13#include "base/task/sequence_manager/task_queue.h"
Sean Mahere672a662023-01-09 21:42:2814#include "base/task/single_thread_task_runner.h"
Carlos Caballero5f6212b2019-05-13 13:45:1615#include "content/common/content_export.h"
16#include "content/public/browser/browser_thread.h"
17
18namespace base {
19namespace sequence_manager {
20class SequenceManager;
Carlos Caballero5f6212b2019-05-13 13:45:1621} // namespace sequence_manager
22} // namespace base
23
24namespace content {
25
26// Common task queues for browser threads. This class holds all the queues
27// needed by browser threads. This makes it easy for all browser threads to have
Chidera Olibief6c4cdb2025-06-25 22:56:0828// the same queues. This class also provides a Handler to act on the queues from
Carlos Caballero5f6212b2019-05-13 13:45:1629// any thread.
30//
31// Instances must be created and destroyed on the same thread as the
32// underlying SequenceManager and instances are not allowed to outlive this
33// SequenceManager. All methods of this class must be called from the
34// associated thread unless noted otherwise. If you need to perform operations
Minoru Chikamunea0317562022-03-22 15:30:2135// from a different thread use a Handle instance instead.
Carlos Caballero5f6212b2019-05-13 13:45:1636//
Carlos Caballero72e8a202019-05-21 16:51:1737// Attention: All queues are initially disabled, that is, tasks will not be run
38// for them.
Carlos Caballero5f6212b2019-05-13 13:45:1639class CONTENT_EXPORT BrowserTaskQueues {
40 public:
41 enum class QueueType {
42 // Catch all for tasks that don't fit other categories.
43 // TODO(alexclarke): Introduce new semantic types as needed to minimize the
Alex Clarkeb7eb45c2019-07-10 15:19:2444 // number of default tasks. Has the same priority as kUserBlocking.
Carlos Caballero5f6212b2019-05-13 13:45:1645 kDefault,
46
47 // For non-urgent work, that will only execute if there's nothing else to
48 // do. Can theoretically be starved indefinitely although that's unlikely in
49 // practice.
50 kBestEffort,
51
Alex Clarkeb7eb45c2019-07-10 15:19:2452 // base::TaskPriority::kUserBlocking maps to this task queue. It's for tasks
53 // that affect the UI immediately after a user interaction. Has the same
54 // priority as kDefault.
Carlos Caballero5f6212b2019-05-13 13:45:1655 kUserBlocking,
56
Alex Clarkeb7eb45c2019-07-10 15:19:2457 // base::TaskPriority::kUserVisible maps to this task queue. The result of
58 // these tasks are visible to the user (in the UI or as a side-effect on the
59 // system) but they are not an immediate response to a user interaction.
60 kUserVisible,
61
Stephen Nuskod43825b2021-06-24 19:10:3762 // For tasks directly related to handling input events. This also changes
63 // the priority of yielding to native (to get the user input events faster).
64 // This is higher priority than kUserBlocking.
65 kUserInput,
66
Clark DuVall6429553c2021-10-06 02:53:1567 // For tasks processing navigation network request's response from the
68 // network service.
69 kNavigationNetworkResponse,
70
Minoru Chikamunea0317562022-03-22 15:30:2171 // For tasks processing ServiceWorker's storage control's response. This has
72 // the highest priority during startup, and is updated to normal priority
73 // after startup.
74 kServiceWorkerStorageControlResponse,
75
Ryan Sturmac5b1662023-06-13 23:31:4776 // For before unload navigation continuation tasks.
77 kBeforeUnloadBrowserResponse,
78
Chidera Olibief6c4cdb2025-06-25 22:56:0879 // Tasks that are critical for startup performance. Note that tasks in other
80 // queues may run during startup too.
81 kStartup,
82
83 kMaxValue = kStartup
Carlos Caballero5f6212b2019-05-13 13:45:1684 };
85
86 static constexpr size_t kNumQueueTypes =
87 static_cast<size_t>(QueueType::kMaxValue) + 1;
88
89 // Handle to a BrowserTaskQueues instance that can be used from any thread
90 // as all operations are thread safe.
91 //
92 // If the underlying BrowserTaskQueues is destroyed all methods of this
93 // class become no-ops, that is it is safe for this class to outlive its
94 // parent BrowserTaskQueues.
Alex Clarke49854cc2019-06-27 08:25:4995 class CONTENT_EXPORT Handle : public base::RefCountedThreadSafe<Handle> {
Carlos Caballero5f6212b2019-05-13 13:45:1696 public:
Alex Clarke49854cc2019-06-27 08:25:4997 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
Carlos Caballero5f6212b2019-05-13 13:45:1698
Carlos Caballero72e8a202019-05-21 16:51:1799 // Returns the task runner that should be returned by
Sean Maher70f2942932023-01-04 22:15:06100 // SingleThreadTaskRunner::GetCurrentDefault().
Carlos Caballero72e8a202019-05-21 16:51:17101 const scoped_refptr<base::SingleThreadTaskRunner>& GetDefaultTaskRunner() {
102 return default_task_runner_;
103 }
104
105 const scoped_refptr<base::SingleThreadTaskRunner>& GetBrowserTaskRunner(
Carlos Caballero5f6212b2019-05-13 13:45:16106 QueueType queue_type) const {
Carlos Caballero72e8a202019-05-21 16:51:17107 return browser_task_runners_[static_cast<size_t>(queue_type)];
Carlos Caballero5f6212b2019-05-13 13:45:16108 }
109
Omar Elmekkawyb081b583a2022-12-17 13:01:27110 // Called after startup is complete, enables all task queues and can
111 // be called multiple times.
Minoru Chikamunea0317562022-03-22 15:30:21112 void OnStartupComplete();
Carlos Caballero72e8a202019-05-21 16:51:17113
Omar Elmekkawyb081b583a2022-12-17 13:01:27114 // Called quite early in startup after initialising the owning thread's
115 // scheduler, before we call RunLoop::Run on the thread.
Carlos Caballero72e8a202019-05-21 16:51:17116 // Enables all task queues except the effort ones. Can be called multiple
117 // times.
118 void EnableAllExceptBestEffortQueues();
Carlos Caballero5f6212b2019-05-13 13:45:16119
Chidera Olibiedebdc542025-03-25 23:14:08120 // Enables the specified task queue. Called early in startup when
121 // BrowserTaskExecutor is created to enabled the default IO task queue.
122 void EnableTaskQueue(QueueType type);
123
Carlos Caballero5f6212b2019-05-13 13:45:16124 // Schedules |on_pending_task_ran| to run when all pending tasks (at the
125 // time this method was invoked) have run. Only "runnable" tasks are taken
126 // into account, that is tasks from disabled queues are ignored, also this
127 // only works reliably for immediate tasks, delayed tasks might or might not
128 // run depending on timing.
129 //
130 // The callback will run on the thread associated with this Handle, unless
131 // that thread is no longer accepting tasks; in which case it will be run
132 // inline immediately.
133 //
134 // The recommended usage pattern is:
135 // RunLoop run_loop;
136 // handle.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure());
137 // run_loop.Run();
138 void ScheduleRunAllPendingTasksForTesting(
139 base::OnceClosure on_pending_task_ran);
140
Tom Sepeza80667c2023-02-13 19:18:46141 // Drop back-pointer to resource about to be freed.
142 void OnTaskQueuesDestroyed() { outer_ = nullptr; }
143
Carlos Caballero5f6212b2019-05-13 13:45:16144 private:
Alex Clarke49854cc2019-06-27 08:25:49145 friend base::RefCountedThreadSafe<Handle>;
146
Carlos Caballero5f6212b2019-05-13 13:45:16147 // Only BrowserTaskQueues can create new instances
148 friend class BrowserTaskQueues;
Alex Clarke49854cc2019-06-27 08:25:49149
150 ~Handle();
151
Carlos Caballero5f6212b2019-05-13 13:45:16152 explicit Handle(BrowserTaskQueues* task_queues);
153
154 // |outer_| can only be safely used from a task posted to one of the
155 // runners.
Kalvin Leeebe9da12023-02-10 10:51:06156 raw_ptr<BrowserTaskQueues> outer_ = nullptr;
Carlos Caballero5f6212b2019-05-13 13:45:16157 scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_;
Carlos Caballero72e8a202019-05-21 16:51:17158 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
Carlos Caballero5f6212b2019-05-13 13:45:16159 std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
Carlos Caballero72e8a202019-05-21 16:51:17160 browser_task_runners_;
Carlos Caballero5f6212b2019-05-13 13:45:16161 };
162
Etienne Pierre-doray40545ac2021-11-11 13:34:28163 // |sequence_manager| must outlive this instance.
Carlos Caballero5f6212b2019-05-13 13:45:16164 explicit BrowserTaskQueues(
165 BrowserThread::ID thread_id,
Etienne Pierre-doray40545ac2021-11-11 13:34:28166 base::sequence_manager::SequenceManager* sequence_manager);
Carlos Caballero5f6212b2019-05-13 13:45:16167
Anand Ravi5e3bf102025-05-02 15:24:49168 void SetOnTaskCompletedHandler(
169 base::sequence_manager::TaskQueue::OnTaskCompletedHandler handler);
170
Carlos Caballero5f6212b2019-05-13 13:45:16171 // Destroys all queues.
172 ~BrowserTaskQueues();
173
Alex Clarke49854cc2019-06-27 08:25:49174 scoped_refptr<Handle> GetHandle() { return handle_; }
Carlos Caballero5f6212b2019-05-13 13:45:16175
mikt541ac712025-08-04 03:16:22176 void AddTaskObserver(base::TaskObserver* task_observer);
177
Carlos Caballero5f6212b2019-05-13 13:45:16178 private:
Scott Haseley20ccbe322023-04-26 20:25:14179 struct QueueData {
180 public:
181 QueueData();
182 ~QueueData();
183 QueueData(QueueData&& other);
184
Scott Haseleya8d3cff12023-06-26 18:12:38185 base::sequence_manager::TaskQueue::Handle task_queue;
Scott Haseley20ccbe322023-04-26 20:25:14186 std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter> voter;
187 };
188
Carlos Caballero5f6212b2019-05-13 13:45:16189 // All these methods can only be called from the associated thread. To make
190 // sure that is the case they will always be called from a task posted to the
191 // |control_queue_|.
192 void StartRunAllPendingTasksForTesting(
193 base::ScopedClosureRunner on_pending_task_ran);
194 void EndRunAllPendingTasksForTesting(
195 base::ScopedClosureRunner on_pending_task_ran);
Minoru Chikamunea0317562022-03-22 15:30:21196 void OnStartupComplete();
Carlos Caballero72e8a202019-05-21 16:51:17197 void EnableAllExceptBestEffortQueues();
Chidera Olibiedebdc542025-03-25 23:14:08198 void EnableTaskQueue(QueueType type);
Carlos Caballero5f6212b2019-05-13 13:45:16199
Carlos Caballero72e8a202019-05-21 16:51:17200 base::sequence_manager::TaskQueue* GetBrowserTaskQueue(QueueType type) const {
Scott Haseley20ccbe322023-04-26 20:25:14201 return queue_data_[static_cast<size_t>(type)].task_queue.get();
202 }
203
204 base::sequence_manager::TaskQueue* GetDefaultTaskQueue() const {
205 return GetBrowserTaskQueue(QueueType::kDefault);
Carlos Caballero5f6212b2019-05-13 13:45:16206 }
207
208 std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes>
Carlos Caballero72e8a202019-05-21 16:51:17209 CreateBrowserTaskRunners() const;
Carlos Caballero5f6212b2019-05-13 13:45:16210
Alex Clarke49854cc2019-06-27 08:25:49211 std::array<QueueData, kNumQueueTypes> queue_data_;
Carlos Caballero72e8a202019-05-21 16:51:17212
Carlos Caballero5f6212b2019-05-13 13:45:16213 // Helper queue to make sure private methods run on the associated thread. the
214 // control queue has maximum priority and will never be disabled.
Scott Haseleya8d3cff12023-06-26 18:12:38215 base::sequence_manager::TaskQueue::Handle control_queue_;
Carlos Caballero5f6212b2019-05-13 13:45:16216
Carlos Caballero5f6212b2019-05-13 13:45:16217 // Helper queue to run all pending tasks.
Scott Haseleya8d3cff12023-06-26 18:12:38218 base::sequence_manager::TaskQueue::Handle run_all_pending_tasks_queue_;
Carlos Caballero5f6212b2019-05-13 13:45:16219 int run_all_pending_nesting_level_ = 0;
Alex Clarke49854cc2019-06-27 08:25:49220
221 scoped_refptr<Handle> handle_;
Carlos Caballero5f6212b2019-05-13 13:45:16222};
223
224} // namespace content
225
226#endif // CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_