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_SINGLE_THREAD_TASK_RUNNER_H_ 6 #define BASE_TASK_SINGLE_THREAD_TASK_RUNNER_H_ 7 8 #include <optional> 9 10 #include "base/auto_reset.h" 11 #include "base/base_export.h" 12 #include "base/dcheck_is_on.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/raw_ptr.h" 15 #include "base/task/sequenced_task_runner.h" 16 17 namespace blink::scheduler { 18 class MainThreadSchedulerImpl; 19 } // namespace blink::scheduler 20 21 namespace base::sequence_manager::internal { 22 class CurrentDefaultHandleOverrideForRunOrPostTask; 23 } 24 25 namespace base { 26 27 class ScopedDisallowRunningRunLoop; 28 29 // A SingleThreadTaskRunner is a SequencedTaskRunner with one more 30 // guarantee; namely, that all tasks are run on a single dedicated 31 // thread. Most use cases require only a SequencedTaskRunner, unless 32 // there is a specific need to run tasks on only a single thread. 33 // 34 // SingleThreadTaskRunner implementations might: 35 // - Post tasks to an existing thread's MessageLoop (see 36 // MessageLoop::task_runner()). 37 // - Create their own worker thread and MessageLoop to post tasks to. 38 // - Add tasks to a FIFO and signal to a non-MessageLoop thread for them to 39 // be processed. This allows TaskRunner-oriented code run on threads 40 // running other kinds of message loop, e.g. Jingle threads. 41 class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner { 42 public: 43 // Returns true if the `SingleThreadTaskRunner` runs tasks posted to it on the 44 // current thread. 45 // 46 // Identical to `RunsTaskInCurrentSequence()`, except from a `RunOrPostTask()` 47 // callback running synchronously (in that case, `BelongsToCurrentThread()` 48 // returns false and `RunsTaskInCurrentSequence()` returns true). 49 virtual bool BelongsToCurrentThread() const; 50 51 // Returns the default SingleThreadTaskRunner for the current thread. 52 // On threads that service multiple task queues, the default task queue is 53 // preferred to inheriting the current task queue (otherwise, everything would 54 // implicitly be "input priority"...). If the caller knows which task queue it 55 // should be running on, it should post to that SingleThreadTaskRunner 56 // directly instead of GetCurrentDefault(). This is critical in some 57 // cases, e.g. DeleteSoon or RefCountedDeleteOnSequence should delete the 58 // object on the same task queue it's used from (or on a lower priority). 59 // 60 // DCHECKs if the current thread isn't servicing a SingleThreadTaskRunner. 61 // 62 // See 63 // https://chromium.googlesource.com/chromium/src/+/main/docs/threading_and_tasks.md#Posting-to-the-Current-Virtual_Thread 64 // for details 65 66 [[nodiscard]] static const scoped_refptr<SingleThreadTaskRunner>& 67 GetCurrentDefault(); 68 69 // Returns true if the SingleThreadTaskRunner is already created for 70 // the current thread. 71 [[nodiscard]] static bool HasCurrentDefault(); 72 73 class CurrentHandleOverrideForTesting; 74 75 class BASE_EXPORT CurrentDefaultHandle { 76 public: 77 // Sets the value returned by `SingleThreadTaskRunner::GetCurrentDefault()` 78 // and `SequencedTaskRunner::GetCurrentDefault()` to `task_runner` within 79 // its scope. `task_runner` must belong to the current thread. There must 80 // not already be a current default `SingleThreadTaskRunner` on this thread. 81 explicit CurrentDefaultHandle( 82 scoped_refptr<SingleThreadTaskRunner> task_runner); 83 84 CurrentDefaultHandle(const CurrentDefaultHandle&) = delete; 85 CurrentDefaultHandle& operator=(const CurrentDefaultHandle&) = delete; 86 87 ~CurrentDefaultHandle(); 88 89 private: 90 friend class SingleThreadTaskRunner; 91 92 // Overriding an existing current default SingleThreadTaskRunner should only 93 // be needed under special circumstances. Require them to be enumerated as 94 // friends to require //base/OWNERS review. Use 95 // SingleThreadTaskRunner::CurrentHandleOverrideForTesting in unit tests to 96 // avoid the friend requirement. 97 friend class blink::scheduler::MainThreadSchedulerImpl; 98 friend class CurrentHandleOverrideForTesting; 99 friend class sequence_manager::internal:: 100 CurrentDefaultHandleOverrideForRunOrPostTask; 101 FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, 102 NestedRunLoopAllowedUnderHandleOverride); 103 FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, 104 NestedOverrideWithMayAlreadyExist); 105 FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, 106 OverrideWithNull); 107 FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, 108 OverrideWithNonNull); 109 110 struct MayAlreadyExist {}; 111 112 // Same as the public constructor, but there may already be a current 113 // default `SingleThreadTaskRunner` on this thread. 114 CurrentDefaultHandle(scoped_refptr<SingleThreadTaskRunner> task_runner, 115 MayAlreadyExist); 116 117 scoped_refptr<SingleThreadTaskRunner> task_runner_; 118 raw_ptr<CurrentDefaultHandle> previous_handle_; 119 SequencedTaskRunner::CurrentDefaultHandle sequenced_handle_; 120 }; 121 122 // Overrides the current default `SingleThreadTaskRunner` and disables running 123 // a `RunLoop` within its scope. 124 // 125 // Note: Overriding the current default SingleThreadTaskRunner isn't generally 126 // desired but it's useful in some unit tests where multiple task runners 127 // share the main thread for simplicity and determinism. Only use this when no 128 // other constructs will work (see base/test/task_environment.h and 129 // base/test/test_mock_time_task_runner.h for preferred alternatives). 130 class BASE_EXPORT CurrentHandleOverrideForTesting { 131 public: 132 explicit CurrentHandleOverrideForTesting( 133 scoped_refptr<SingleThreadTaskRunner> overriding_task_runner); 134 ~CurrentHandleOverrideForTesting(); 135 136 private: 137 CurrentDefaultHandle current_default_handle_; 138 std::unique_ptr<ScopedDisallowRunningRunLoop> no_running_during_override_; 139 }; 140 141 protected: 142 ~SingleThreadTaskRunner() override = default; 143 }; 144 145 } // namespace base 146 147 #endif // BASE_TASK_SINGLE_THREAD_TASK_RUNNER_H_ 148