1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // 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 10 #include "base/callback_helpers.h" 11 #include "base/memory/scoped_refptr.h" 12 #include "base/task/sequence_manager/task_queue.h" 13 #include "content/common/content_export.h" 14 #include "content/public/browser/browser_thread.h" 15 16 namespace base { 17 namespace sequence_manager { 18 class SequenceManager; 19 class TimeDomain; 20 } // namespace sequence_manager 21 } // namespace base 22 23 namespace content { 24 25 // Common task queues for browser threads. This class holds all the queues 26 // needed by browser threads. This makes it easy for all browser threads to have 27 // the same queues. Thic class also provides a Handler to act on the queues from 28 // any thread. 29 // 30 // Instances must be created and destroyed on the same thread as the 31 // underlying SequenceManager and instances are not allowed to outlive this 32 // SequenceManager. All methods of this class must be called from the 33 // associated thread unless noted otherwise. If you need to perform operations 34 // from a different thread use the a Handle instance instead. 35 // 36 // Attention: All queues are initially disabled, that is, tasks will not be run 37 // for them. 38 class CONTENT_EXPORT BrowserTaskQueues { 39 public: 40 enum class QueueType { 41 // Catch all for tasks that don't fit other categories. 42 // TODO(alexclarke): Introduce new semantic types as needed to minimize the 43 // number of default tasks. Has the same priority as kUserBlocking. 44 kDefault, 45 46 // For non-urgent work, that will only execute if there's nothing else to 47 // do. Can theoretically be starved indefinitely although that's unlikely in 48 // practice. 49 kBestEffort, 50 51 // For tasks on the critical path up to issuing the initial navigation. 52 kBootstrap, 53 54 // For preconnection-related tasks. 55 kPreconnection, 56 57 // base::TaskPriority::kUserBlocking maps to this task queue. It's for tasks 58 // that affect the UI immediately after a user interaction. Has the same 59 // priority as kDefault. 60 kUserBlocking, 61 62 // base::TaskPriority::kUserVisible maps to this task queue. The result of 63 // these tasks are visible to the user (in the UI or as a side-effect on the 64 // system) but they are not an immediate response to a user interaction. 65 kUserVisible, 66 67 kMaxValue = kUserVisible 68 }; 69 70 static constexpr size_t kNumQueueTypes = 71 static_cast<size_t>(QueueType::kMaxValue) + 1; 72 73 // Handle to a BrowserTaskQueues instance that can be used from any thread 74 // as all operations are thread safe. 75 // 76 // If the underlying BrowserTaskQueues is destroyed all methods of this 77 // class become no-ops, that is it is safe for this class to outlive its 78 // parent BrowserTaskQueues. 79 class CONTENT_EXPORT Handle : public base::RefCountedThreadSafe<Handle> { 80 public: 81 REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE(); 82 83 // Returns the task runner that should be returned by 84 // ThreadTaskRunnerHandle::Get(). GetDefaultTaskRunner()85 const scoped_refptr<base::SingleThreadTaskRunner>& GetDefaultTaskRunner() { 86 return default_task_runner_; 87 } 88 GetBrowserTaskRunner(QueueType queue_type)89 const scoped_refptr<base::SingleThreadTaskRunner>& GetBrowserTaskRunner( 90 QueueType queue_type) const { 91 return browser_task_runners_[static_cast<size_t>(queue_type)]; 92 } 93 94 // Initializes any scheduler experiments. Should be called after 95 // FeatureLists have been initialized (which usually happens after task 96 // queues are set up). 97 void PostFeatureListInitializationSetup(); 98 99 // Enables all tasks queues. Can be called multiple times. 100 void EnableAllQueues(); 101 102 // Enables all task queues except the effort ones. Can be called multiple 103 // times. 104 void EnableAllExceptBestEffortQueues(); 105 106 // Schedules |on_pending_task_ran| to run when all pending tasks (at the 107 // time this method was invoked) have run. Only "runnable" tasks are taken 108 // into account, that is tasks from disabled queues are ignored, also this 109 // only works reliably for immediate tasks, delayed tasks might or might not 110 // run depending on timing. 111 // 112 // The callback will run on the thread associated with this Handle, unless 113 // that thread is no longer accepting tasks; in which case it will be run 114 // inline immediately. 115 // 116 // The recommended usage pattern is: 117 // RunLoop run_loop; 118 // handle.ScheduleRunAllPendingTasksForTesting(run_loop.QuitClosure()); 119 // run_loop.Run(); 120 void ScheduleRunAllPendingTasksForTesting( 121 base::OnceClosure on_pending_task_ran); 122 123 private: 124 friend base::RefCountedThreadSafe<Handle>; 125 126 // Only BrowserTaskQueues can create new instances 127 friend class BrowserTaskQueues; 128 129 ~Handle(); 130 131 explicit Handle(BrowserTaskQueues* task_queues); 132 133 // |outer_| can only be safely used from a task posted to one of the 134 // runners. 135 BrowserTaskQueues* outer_ = nullptr; 136 scoped_refptr<base::SingleThreadTaskRunner> control_task_runner_; 137 scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_; 138 std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes> 139 browser_task_runners_; 140 }; 141 142 // |sequence_manager| and |time_domain| must outlive this instance. 143 explicit BrowserTaskQueues( 144 BrowserThread::ID thread_id, 145 base::sequence_manager::SequenceManager* sequence_manager, 146 base::sequence_manager::TimeDomain* time_domain); 147 148 // Destroys all queues. 149 ~BrowserTaskQueues(); 150 GetHandle()151 scoped_refptr<Handle> GetHandle() { return handle_; } 152 153 private: 154 // All these methods can only be called from the associated thread. To make 155 // sure that is the case they will always be called from a task posted to the 156 // |control_queue_|. 157 void StartRunAllPendingTasksForTesting( 158 base::ScopedClosureRunner on_pending_task_ran); 159 void EndRunAllPendingTasksForTesting( 160 base::ScopedClosureRunner on_pending_task_ran); 161 void EnableAllQueues(); 162 void EnableAllExceptBestEffortQueues(); 163 void PostFeatureListInitializationSetup(); 164 GetBrowserTaskQueue(QueueType type)165 base::sequence_manager::TaskQueue* GetBrowserTaskQueue(QueueType type) const { 166 return queue_data_[static_cast<size_t>(type)].task_queue.get(); 167 } 168 169 std::array<scoped_refptr<base::SingleThreadTaskRunner>, kNumQueueTypes> 170 CreateBrowserTaskRunners() const; 171 172 struct QueueData { 173 QueueData(); 174 ~QueueData(); 175 scoped_refptr<base::sequence_manager::TaskQueue> task_queue; 176 std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter> voter; 177 }; 178 std::array<QueueData, kNumQueueTypes> queue_data_; 179 180 // Helper queue to make sure private methods run on the associated thread. the 181 // control queue has maximum priority and will never be disabled. 182 scoped_refptr<base::sequence_manager::TaskQueue> control_queue_; 183 184 // Queue that backs the default TaskRunner registered with SequenceManager. 185 // This will be the one returned by ThreadTaskRunnerHandle::Get(). Note this 186 // is different from QueueType:kDefault as this queue needs to be enabled from 187 // the beginning. 188 scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_; 189 190 // Helper queue to run all pending tasks. 191 scoped_refptr<base::sequence_manager::TaskQueue> run_all_pending_tasks_queue_; 192 int run_all_pending_nesting_level_ = 0; 193 194 scoped_refptr<Handle> handle_; 195 }; 196 197 } // namespace content 198 199 #endif // CONTENT_BROWSER_SCHEDULER_BROWSER_TASK_QUEUES_H_ 200