1 // Copyright 2016 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 BASE_TASK_SCHEDULER_TASK_SCHEDULER_H_ 6 #define BASE_TASK_SCHEDULER_TASK_SCHEDULER_H_ 7 8 #include <memory> 9 #include <vector> 10 11 #include "base/base_export.h" 12 #include "base/callback.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/sequenced_task_runner.h" 16 #include "base/single_thread_task_runner.h" 17 #include "base/strings/string_piece.h" 18 #include "base/task_runner.h" 19 #include "base/task_scheduler/scheduler_worker_pool_params.h" 20 #include "base/task_scheduler/single_thread_task_runner_thread_mode.h" 21 #include "base/task_scheduler/task_traits.h" 22 #include "base/time/time.h" 23 #include "build/build_config.h" 24 25 namespace gin { 26 class V8Platform; 27 } 28 29 namespace content { 30 // Can't use the FRIEND_TEST_ALL_PREFIXES macro because the test is in a 31 // different namespace. 32 class BrowserMainLoopTest_CreateThreadsInSingleProcess_Test; 33 } // namespace content 34 35 namespace base { 36 37 class HistogramBase; 38 class Location; 39 class SchedulerWorkerObserver; 40 41 // Interface for a task scheduler and static methods to manage the instance used 42 // by the post_task.h API. 43 // 44 // The task scheduler doesn't create threads until Start() is called. Tasks can 45 // be posted at any time but will not run until after Start() is called. 46 // 47 // The instance methods of this class are thread-safe. 48 // 49 // Note: All base/task_scheduler users should go through post_task.h instead of 50 // TaskScheduler except for the one callsite per process which manages the 51 // process's instance. 52 class BASE_EXPORT TaskScheduler { 53 public: 54 struct BASE_EXPORT InitParams { 55 enum class SharedWorkerPoolEnvironment { 56 // Use the default environment (no environment). 57 DEFAULT, 58 #if defined(OS_WIN) 59 // Place the worker in a COM MTA. 60 COM_MTA, 61 #endif // defined(OS_WIN) 62 }; 63 64 InitParams( 65 const SchedulerWorkerPoolParams& background_worker_pool_params_in, 66 const SchedulerWorkerPoolParams& 67 background_blocking_worker_pool_params_in, 68 const SchedulerWorkerPoolParams& foreground_worker_pool_params_in, 69 const SchedulerWorkerPoolParams& 70 foreground_blocking_worker_pool_params_in, 71 SharedWorkerPoolEnvironment shared_worker_pool_environment_in = 72 SharedWorkerPoolEnvironment::DEFAULT); 73 ~InitParams(); 74 75 SchedulerWorkerPoolParams background_worker_pool_params; 76 SchedulerWorkerPoolParams background_blocking_worker_pool_params; 77 SchedulerWorkerPoolParams foreground_worker_pool_params; 78 SchedulerWorkerPoolParams foreground_blocking_worker_pool_params; 79 SharedWorkerPoolEnvironment shared_worker_pool_environment; 80 }; 81 82 // Destroying a TaskScheduler is not allowed in production; it is always 83 // leaked. In tests, it should only be destroyed after JoinForTesting() has 84 // returned. 85 virtual ~TaskScheduler() = default; 86 87 // Allows the task scheduler to create threads and run tasks following the 88 // |init_params| specification. 89 // 90 // If specified, |scheduler_worker_observer| will be notified when a worker 91 // enters and exits its main function. It must not be destroyed before 92 // JoinForTesting() has returned (must never be destroyed in production). 93 // 94 // CHECKs on failure. 95 virtual void Start( 96 const InitParams& init_params, 97 SchedulerWorkerObserver* scheduler_worker_observer = nullptr) = 0; 98 99 // Posts |task| with a |delay| and specific |traits|. |delay| can be zero. 100 // For one off tasks that don't require a TaskRunner. 101 virtual void PostDelayedTaskWithTraits(const Location& from_here, 102 const TaskTraits& traits, 103 OnceClosure task, 104 TimeDelta delay) = 0; 105 106 // Returns a TaskRunner whose PostTask invocations result in scheduling tasks 107 // using |traits|. Tasks may run in any order and in parallel. 108 virtual scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits( 109 const TaskTraits& traits) = 0; 110 111 // Returns a SequencedTaskRunner whose PostTask invocations result in 112 // scheduling tasks using |traits|. Tasks run one at a time in posting order. 113 virtual scoped_refptr<SequencedTaskRunner> 114 CreateSequencedTaskRunnerWithTraits(const TaskTraits& traits) = 0; 115 116 // Returns a SingleThreadTaskRunner whose PostTask invocations result in 117 // scheduling tasks using |traits|. Tasks run on a single thread in posting 118 // order. 119 virtual scoped_refptr<SingleThreadTaskRunner> 120 CreateSingleThreadTaskRunnerWithTraits( 121 const TaskTraits& traits, 122 SingleThreadTaskRunnerThreadMode thread_mode) = 0; 123 124 #if defined(OS_WIN) 125 // Returns a SingleThreadTaskRunner whose PostTask invocations result in 126 // scheduling tasks using |traits| in a COM Single-Threaded Apartment. Tasks 127 // run in the same Single-Threaded Apartment in posting order for the returned 128 // SingleThreadTaskRunner. There is not necessarily a one-to-one 129 // correspondence between SingleThreadTaskRunners and Single-Threaded 130 // Apartments. The implementation is free to share apartments or create new 131 // apartments as necessary. In either case, care should be taken to make sure 132 // COM pointers are not smuggled across apartments. 133 virtual scoped_refptr<SingleThreadTaskRunner> 134 CreateCOMSTATaskRunnerWithTraits( 135 const TaskTraits& traits, 136 SingleThreadTaskRunnerThreadMode thread_mode) = 0; 137 #endif // defined(OS_WIN) 138 139 // Returns a vector of all histograms available in this task scheduler. 140 virtual std::vector<const HistogramBase*> GetHistograms() const = 0; 141 142 // Synchronously shuts down the scheduler. Once this is called, only tasks 143 // posted with the BLOCK_SHUTDOWN behavior will be run. When this returns: 144 // - All SKIP_ON_SHUTDOWN tasks that were already running have completed their 145 // execution. 146 // - All posted BLOCK_SHUTDOWN tasks have completed their execution. 147 // - CONTINUE_ON_SHUTDOWN tasks might still be running. 148 // Note that an implementation can keep threads and other resources alive to 149 // support running CONTINUE_ON_SHUTDOWN after this returns. This can only be 150 // called once. 151 virtual void Shutdown() = 0; 152 153 // Waits until there are no pending undelayed tasks. May be called in tests 154 // to validate that a condition is met after all undelayed tasks have run. 155 // 156 // Does not wait for delayed tasks. Waits for undelayed tasks posted from 157 // other threads during the call. Returns immediately when shutdown completes. 158 virtual void FlushForTesting() = 0; 159 160 // Returns and calls |flush_callback| when there are no incomplete undelayed 161 // tasks. |flush_callback| may be called back on any thread and should not 162 // perform a lot of work. May be used when additional work on the current 163 // thread needs to be performed during a flush. Only one 164 // FlushAsyncForTesting() may be pending at any given time. 165 virtual void FlushAsyncForTesting(OnceClosure flush_callback) = 0; 166 167 // Joins all threads. Tasks that are already running are allowed to complete 168 // their execution. This can only be called once. Using this task scheduler 169 // instance to create task runners or post tasks is not permitted during or 170 // after this call. 171 virtual void JoinForTesting() = 0; 172 173 // CreateAndStartWithDefaultParams(), Create(), and SetInstance() register a 174 // TaskScheduler to handle tasks posted through the post_task.h API for this 175 // process. 176 // 177 // Processes that need to initialize TaskScheduler with custom params or that 178 // need to allow tasks to be posted before the TaskScheduler creates its 179 // threads should use Create() followed by Start(). Other processes can use 180 // CreateAndStartWithDefaultParams(). 181 // 182 // A registered TaskScheduler is only deleted when a new TaskScheduler is 183 // registered. The last registered TaskScheduler is leaked on shutdown. The 184 // methods below must not be called when TaskRunners created by a previous 185 // TaskScheduler are still alive. The methods are not thread-safe; proper 186 // synchronization is required to use the post_task.h API after registering a 187 // new TaskScheduler. 188 189 #if !defined(OS_NACL) 190 // Creates and starts a task scheduler using default params. |name| is used to 191 // label histograms, it must not be empty. It should identify the component 192 // that calls this. Start() is called by this method; it is invalid to call it 193 // again afterwards. CHECKs on failure. For tests, prefer 194 // base::test::ScopedTaskEnvironment (ensures isolation). 195 static void CreateAndStartWithDefaultParams(StringPiece name); 196 197 // Same as CreateAndStartWithDefaultParams() but allows callers to split the 198 // Create() and StartWithDefaultParams() calls. 199 void StartWithDefaultParams(); 200 #endif // !defined(OS_NACL) 201 202 // Creates a ready to start task scheduler. |name| is used to label 203 // histograms, it must not be empty. It should identify the component that 204 // creates the TaskScheduler. The task scheduler doesn't create threads until 205 // Start() is called. Tasks can be posted at any time but will not run until 206 // after Start() is called. For tests, prefer 207 // base::test::ScopedTaskEnvironment (ensures isolation). 208 static void Create(StringPiece name); 209 210 // Registers |task_scheduler| to handle tasks posted through the post_task.h 211 // API for this process. For tests, prefer base::test::ScopedTaskEnvironment 212 // (ensures isolation). 213 static void SetInstance(std::unique_ptr<TaskScheduler> task_scheduler); 214 215 // Retrieve the TaskScheduler set via SetInstance() or 216 // CreateAndSet(Simple|Default)TaskScheduler(). This should be used very 217 // rarely; most users of TaskScheduler should use the post_task.h API. In 218 // particular, refrain from doing 219 // if (!TaskScheduler::GetInstance()) { 220 // TaskScheduler::SetInstance(...); 221 // base::PostTask(...); 222 // } 223 // instead make sure to SetInstance() early in one determinstic place in the 224 // process' initialization phase. 225 // In doubt, consult with //base/task_scheduler/OWNERS. 226 static TaskScheduler* GetInstance(); 227 228 private: 229 friend class gin::V8Platform; 230 friend class content::BrowserMainLoopTest_CreateThreadsInSingleProcess_Test; 231 232 // Returns the maximum number of non-single-threaded non-blocked tasks posted 233 // with |traits| that can run concurrently in this TaskScheduler. |traits| 234 // can't contain TaskPriority::BACKGROUND. 235 // 236 // Do not use this method. To process n items, post n tasks that each process 237 // 1 item rather than GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated() 238 // tasks that each process 239 // n/GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated() items. 240 // 241 // TODO(fdoray): Remove this method. https://crbug.com/687264 242 virtual int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated( 243 const TaskTraits& traits) const = 0; 244 }; 245 246 } // namespace base 247 248 #endif // BASE_TASK_SCHEDULER_TASK_SCHEDULER_H_ 249