1 // Copyright 2012 The Chromium Authors 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_SEQUENCED_TASK_RUNNER_H_ 6 #define BASE_TASK_SEQUENCED_TASK_RUNNER_H_ 7 8 #include <memory> 9 10 #include "base/auto_reset.h" 11 #include "base/base_export.h" 12 #include "base/functional/callback.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/raw_ptr_exclusion.h" 15 #include "base/task/delay_policy.h" 16 #include "base/task/delayed_task_handle.h" 17 #include "base/task/sequenced_task_runner_helpers.h" 18 #include "base/task/task_runner.h" 19 #include "base/types/pass_key.h" 20 21 namespace blink { 22 class LowPrecisionTimer; 23 class ScriptedIdleTaskController; 24 class TimerBase; 25 class TimerBasedTickProvider; 26 class WebRtcTaskQueue; 27 } 28 namespace IPC { 29 class ChannelAssociatedGroupController; 30 } // namespace IPC 31 namespace media { 32 class AlsaPcmOutputStream; 33 class AlsaPcmInputStream; 34 class FakeAudioWorker; 35 } // namespace media 36 namespace viz { 37 class ExternalBeginFrameSourceWin; 38 } // namespace viz 39 namespace webrtc { 40 class ThreadWrapper; 41 } // namespace webrtc 42 43 namespace base { 44 45 namespace android { 46 class PreFreezeBackgroundMemoryTrimmer; 47 } 48 namespace internal { 49 class DelayTimerBase; 50 class DelayedTaskManager; 51 } 52 class DeadlineTimer; 53 class MetronomeTimer; 54 class SingleThreadTaskRunner; 55 class TimeDelta; 56 class TimeTicks; 57 58 namespace subtle { 59 60 // Restricts access to PostCancelableDelayedTask*() to authorized callers. 61 class PostDelayedTaskPassKey { 62 private: 63 // Avoid =default to disallow creation by uniform initialization. 64 PostDelayedTaskPassKey() = default; 65 66 friend class base::internal::DelayTimerBase; 67 friend class base::internal::DelayedTaskManager; 68 friend class base::DeadlineTimer; 69 friend class base::MetronomeTimer; 70 friend class blink::LowPrecisionTimer; 71 friend class blink::ScriptedIdleTaskController; 72 friend class blink::TimerBase; 73 friend class blink::TimerBasedTickProvider; 74 friend class blink::WebRtcTaskQueue; 75 friend class PostDelayedTaskPassKeyForTesting; 76 friend class webrtc::ThreadWrapper; 77 friend class media::AlsaPcmOutputStream; 78 friend class media::AlsaPcmInputStream; 79 friend class media::FakeAudioWorker; 80 #if BUILDFLAG(IS_ANDROID) 81 friend class base::android::PreFreezeBackgroundMemoryTrimmer; 82 #endif 83 }; 84 85 // Restricts access to RunOrPostTask() to authorized callers. 86 class RunOrPostTaskPassKey { 87 private: 88 // Avoid =default to disallow creation by uniform initialization. 89 RunOrPostTaskPassKey() = default; 90 91 friend class IPC::ChannelAssociatedGroupController; 92 friend class RunOrPostTaskPassKeyForTesting; 93 friend class viz::ExternalBeginFrameSourceWin; 94 }; 95 96 class PostDelayedTaskPassKeyForTesting : public PostDelayedTaskPassKey {}; 97 class RunOrPostTaskPassKeyForTesting : public RunOrPostTaskPassKey {}; 98 99 } // namespace subtle 100 101 // A SequencedTaskRunner is a subclass of TaskRunner that provides 102 // additional guarantees on the order that tasks are started, as well 103 // as guarantees on when tasks are in sequence, i.e. one task finishes 104 // before the other one starts. 105 // 106 // Summary 107 // ------- 108 // Non-nested tasks with the same delay will run one by one in FIFO 109 // order. 110 // 111 // Detailed guarantees 112 // ------------------- 113 // 114 // SequencedTaskRunner also adds additional methods for posting 115 // non-nestable tasks. In general, an implementation of TaskRunner 116 // may expose task-running methods which are themselves callable from 117 // within tasks. A non-nestable task is one that is guaranteed to not 118 // be run from within an already-running task. Conversely, a nestable 119 // task (the default) is a task that can be run from within an 120 // already-running task. 121 // 122 // The guarantees of SequencedTaskRunner are as follows: 123 // 124 // - Given two tasks T2 and T1, T2 will start after T1 starts if: 125 // 126 // * T2 is posted after T1; and 127 // * T2 has equal or higher delay than T1; and 128 // * T2 is non-nestable or T1 is nestable. 129 // 130 // - If T2 will start after T1 starts by the above guarantee, then 131 // T2 will start after T1 finishes and is destroyed if: 132 // 133 // * T2 is non-nestable, or 134 // * T1 doesn't call any task-running methods. 135 // 136 // - If T2 will start after T1 finishes by the above guarantee, then 137 // all memory changes in T1 and T1's destruction will be visible 138 // to T2. 139 // 140 // - If T2 runs nested within T1 via a call to the task-running 141 // method M, then all memory changes in T1 up to the call to M 142 // will be visible to T2, and all memory changes in T2 will be 143 // visible to T1 from the return from M. 144 // 145 // Note that SequencedTaskRunner does not guarantee that tasks are run 146 // on a single dedicated thread, although the above guarantees provide 147 // most (but not all) of the same guarantees. If you do need to 148 // guarantee that tasks are run on a single dedicated thread, see 149 // SingleThreadTaskRunner (in single_thread_task_runner.h). 150 // 151 // Some corollaries to the above guarantees, assuming the tasks in 152 // question don't call any task-running methods: 153 // 154 // - Tasks posted via PostTask are run in FIFO order. 155 // 156 // - Tasks posted via PostNonNestableTask are run in FIFO order. 157 // 158 // - Tasks posted with the same delay and the same nestable state 159 // are run in FIFO order. 160 // 161 // - A list of tasks with the same nestable state posted in order of 162 // non-decreasing delay is run in FIFO order. 163 // 164 // - A list of tasks posted in order of non-decreasing delay with at 165 // most a single change in nestable state from nestable to 166 // non-nestable is run in FIFO order. (This is equivalent to the 167 // statement of the first guarantee above.) 168 // 169 // Some theoretical implementations of SequencedTaskRunner: 170 // 171 // - A SequencedTaskRunner that wraps a regular TaskRunner but makes 172 // sure that only one task at a time is posted to the TaskRunner, 173 // with appropriate memory barriers in between tasks. 174 // 175 // - A SequencedTaskRunner that, for each task, spawns a joinable 176 // thread to run that task and immediately quit, and then 177 // immediately joins that thread. 178 // 179 // - A SequencedTaskRunner that stores the list of posted tasks and 180 // has a method Run() that runs each runnable task in FIFO order 181 // that can be called from any thread, but only if another 182 // (non-nested) Run() call isn't already happening. 183 // 184 // SequencedTaskRunner::GetCurrentDefault() can be used while running 185 // a task to retrieve the default SequencedTaskRunner for the current 186 // sequence. 187 class BASE_EXPORT SequencedTaskRunner : public TaskRunner { 188 public: 189 // The two PostNonNestable*Task methods below are like their 190 // nestable equivalents in TaskRunner, but they guarantee that the 191 // posted task will not run nested within an already-running task. 192 // 193 // A simple corollary is that posting a task as non-nestable can 194 // only delay when the task gets run. That is, posting a task as 195 // non-nestable may not affect when the task gets run, or it could 196 // make it run later than it normally would, but it won't make it 197 // run earlier than it normally would. 198 199 // TODO(akalin): Get rid of the boolean return value for the methods 200 // below. 201 202 bool PostNonNestableTask(const Location& from_here, OnceClosure task); 203 204 virtual bool PostNonNestableDelayedTask(const Location& from_here, 205 OnceClosure task, 206 base::TimeDelta delay) = 0; 207 208 // Posts the given |task| to be run only after |delay| has passed. Returns a 209 // handle that can be used to cancel the task. This should not be used 210 // directly. Consider using higher level timer primitives in 211 // base/timer/timer.h. 212 // 213 // The handle is only guaranteed valid while the task is pending execution. 214 // This means that it may be invalid if the posting failed, and will be 215 // invalid while the task is executing. Calling CancelTask() on an invalid 216 // handle is a no-op. 217 // 218 // This method and the handle it returns are not thread-safe and can only be 219 // used from the sequence this task runner runs its tasks on. 220 virtual DelayedTaskHandle PostCancelableDelayedTask( 221 subtle::PostDelayedTaskPassKey, 222 const Location& from_here, 223 OnceClosure task, 224 TimeDelta delay); 225 226 // Posts the given |task| to be run at |delayed_run_time| (or immediately if 227 // in the past), following |delay_policy|. Returns a handle that can be used 228 // to cancel the task. This should not be used directly. Consider using higher 229 // level timer primitives in base/timer/timer.h. 230 [[nodiscard]] virtual DelayedTaskHandle PostCancelableDelayedTaskAt( 231 subtle::PostDelayedTaskPassKey, 232 const Location& from_here, 233 OnceClosure task, 234 TimeTicks delayed_run_time, 235 subtle::DelayPolicy delay_policy); 236 237 // Posts the given |task| to be run at |delayed_run_time| (or immediately if 238 // in the past), following |delay_policy|. This is used by the default 239 // implementation of PostCancelableDelayedTaskAt(). The default behavior 240 // subtracts TimeTicks::Now() from |delayed_run_time| to get a delay. See 241 // base::Timer to post precise/repeating timeouts. 242 // TODO(crbug.com/40158967): Make pure virtual once all SequencedTaskRunners 243 // implement this. 244 virtual bool PostDelayedTaskAt(subtle::PostDelayedTaskPassKey, 245 const Location& from_here, 246 OnceClosure task, 247 TimeTicks delayed_run_time, 248 subtle::DelayPolicy delay_policy); 249 250 // May run `task` synchronously if no work that has ordering or mutual 251 // exclusion expectations with tasks from this `SequencedTaskRunner` is 252 // pending or running (if such work arrives after `task` starts running 253 // synchronously, it waits until `task` finishes). Otherwise, behaves like 254 // `PostTask`. Since `task` may run synchronously, it is generally not 255 // appropriate to invoke this if `task` may take a long time to run. 256 // 257 // TODO(crbug.com/40944462): This API is still in development. It doesn't yet 258 // support SequenceLocalStorage. 259 virtual bool RunOrPostTask(subtle::RunOrPostTaskPassKey, 260 const Location& from_here, 261 OnceClosure task); 262 263 // Submits a non-nestable task to delete the given object. Returns 264 // true if the object may be deleted at some point in the future, 265 // and false if the object definitely will not be deleted. 266 // 267 // By default, this leaks `object` if the deleter task doesn't run, e.g. if 268 // the underlying task queue is shut down first. Subclasses can override this 269 // behavior by specializing `DeleteOrReleaseSoonInternal()`. 270 template <class T> DeleteSoon(const Location & from_here,const T * object)271 bool DeleteSoon(const Location& from_here, const T* object) { 272 return DeleteOrReleaseSoonInternal(from_here, &DeleteHelper<T>::DoDelete, 273 object); 274 } 275 276 template <class T> DeleteSoon(const Location & from_here,std::unique_ptr<T> object)277 bool DeleteSoon(const Location& from_here, std::unique_ptr<T> object) { 278 return DeleteOrReleaseSoonInternal( 279 from_here, &DeleteUniquePtrHelper<T>::DoDelete, object.release()); 280 } 281 282 // Submits a non-nestable task to release the given object. 283 // 284 // By default, this leaks `object` if the releaser task doesn't run, e.g. if 285 // the underlying task queue is shut down first. Subclasses can override this 286 // behavior by specializing `DeleteOrReleaseSoonInternal()`. 287 // 288 // ReleaseSoon makes sure that the object it the scoped_refptr points to gets 289 // properly released on the correct thread. 290 // We apply ReleaseSoon to the rvalue as the side-effects can be unclear to 291 // the caller if an lvalue is used. That being so, the scoped_refptr should 292 // always be std::move'd. 293 // Example use: 294 // 295 // scoped_refptr<T> foo_scoped_refptr; 296 // ... 297 // task_runner->ReleaseSoon(std::move(foo_scoped_refptr)); 298 template <class T> ReleaseSoon(const Location & from_here,scoped_refptr<T> && object)299 void ReleaseSoon(const Location& from_here, scoped_refptr<T>&& object) { 300 if (!object) 301 return; 302 303 DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease, 304 object.release()); 305 } 306 307 // Returns true iff tasks posted to this TaskRunner are sequenced 308 // with this call. 309 // 310 // In particular: 311 // - Returns true if this is a SequencedTaskRunner to which the 312 // current task was posted. 313 // - Returns true if this is a SequencedTaskRunner bound to the 314 // same sequence as the SequencedTaskRunner to which the current 315 // task was posted. 316 // - Returns true if this is a SingleThreadTaskRunner bound to 317 // the current thread. 318 virtual bool RunsTasksInCurrentSequence() const = 0; 319 320 // Returns the default SequencedTaskRunner for the current task. It 321 // should only be called if HasCurrentDefault() returns true (see the comment 322 // there for the requirements). 323 // 324 // It is "default" in the sense that if the current sequence multiplexes 325 // multiple task queues (e.g. BrowserThread::UI), this will return the default 326 // task queue. A caller that wants a specific task queue should obtain it 327 // directly instead of going through this API. 328 // 329 // See 330 // https://chromium.googlesource.com/chromium/src/+/main/docs/threading_and_tasks.md#Posting-to-the-Current-Virtual_Thread 331 // for details 332 [[nodiscard]] static const scoped_refptr<SequencedTaskRunner>& 333 GetCurrentDefault(); 334 335 // Returns true if one of the following conditions is fulfilled: 336 // a) A SequencedTaskRunner has been assigned to the current thread by 337 // instantiating a SequencedTaskRunner::CurrentDefaultHandle. 338 // b) The current thread has a SingleThreadTaskRunner::CurrentDefaultHandle 339 // (which includes any thread that runs a MessagePump). 340 [[nodiscard]] static bool HasCurrentDefault(); 341 342 class BASE_EXPORT CurrentDefaultHandle { 343 public: 344 // Sets the value returned by `SequencedTaskRunner::GetCurrentDefault()` to 345 // `task_runner` within its scope. `task_runner` must belong to the current 346 // sequence. There must not already be a current default 347 // `SequencedTaskRunner` on this thread. 348 explicit CurrentDefaultHandle( 349 scoped_refptr<SequencedTaskRunner> task_runner); 350 351 CurrentDefaultHandle(const CurrentDefaultHandle&) = delete; 352 CurrentDefaultHandle& operator=(const CurrentDefaultHandle&) = delete; 353 354 ~CurrentDefaultHandle(); 355 356 private: 357 friend class SequencedTaskRunner; 358 359 // Overriding an existing current default SingleThreadTaskRunner should only 360 // be needed under special circumstances. Require them to be enumerated as 361 // friends to require //base/OWNERS review. Use 362 // SingleThreadTaskRunner::CurrentHandleOverrideForTesting in unit tests to 363 // avoid the friend requirement. 364 friend class SingleThreadTaskRunner; 365 FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerCurrentDefaultHandleTest, 366 OverrideWithNull); 367 FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerCurrentDefaultHandleTest, 368 OverrideWithNonNull); 369 370 struct MayAlreadyExist {}; 371 372 // Same as the public constructor, but there may already be a current 373 // default `SequencedTaskRunner` on this thread. 374 CurrentDefaultHandle(scoped_refptr<SequencedTaskRunner> task_runner, 375 MayAlreadyExist); 376 377 scoped_refptr<SequencedTaskRunner> task_runner_; 378 // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of 379 // speedometer3). 380 RAW_PTR_EXCLUSION CurrentDefaultHandle* previous_handle_ = nullptr; 381 }; 382 383 protected: 384 ~SequencedTaskRunner() override = default; 385 386 virtual bool DeleteOrReleaseSoonInternal(const Location& from_here, 387 void (*deleter)(const void*), 388 const void* object); 389 }; 390 391 // Sample usage with std::unique_ptr : 392 // std::unique_ptr<Foo, base::OnTaskRunnerDeleter> ptr( 393 // new Foo, base::OnTaskRunnerDeleter(my_task_runner)); 394 // 395 // For RefCounted see base::RefCountedDeleteOnSequence. 396 struct BASE_EXPORT OnTaskRunnerDeleter { 397 explicit OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner); 398 ~OnTaskRunnerDeleter(); 399 400 OnTaskRunnerDeleter(OnTaskRunnerDeleter&&); 401 OnTaskRunnerDeleter& operator=(OnTaskRunnerDeleter&&); 402 403 // For compatibility with std:: deleters. 404 template <typename T> operatorOnTaskRunnerDeleter405 void operator()(const T* ptr) { 406 if (ptr) 407 task_runner_->DeleteSoon(FROM_HERE, ptr); 408 } 409 410 scoped_refptr<SequencedTaskRunner> task_runner_; 411 }; 412 413 } // namespace base 414 415 #endif // BASE_TASK_SEQUENCED_TASK_RUNNER_H_ 416