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 "base/auto_reset.h" 9 #include "base/base_export.h" 10 #include "base/dcheck_is_on.h" 11 #include "base/memory/raw_ptr_exclusion.h" 12 #include "base/task/sequenced_task_runner.h" 13 #include "third_party/abseil-cpp/absl/types/optional.h" 14 15 namespace blink::scheduler { 16 class MainThreadSchedulerImpl; 17 } // namespace blink::scheduler 18 19 namespace base { 20 21 class ScopedDisallowRunningRunLoop; 22 23 // A SingleThreadTaskRunner is a SequencedTaskRunner with one more 24 // guarantee; namely, that all tasks are run on a single dedicated 25 // thread. Most use cases require only a SequencedTaskRunner, unless 26 // there is a specific need to run tasks on only a single thread. 27 // 28 // SingleThreadTaskRunner implementations might: 29 // - Post tasks to an existing thread's MessageLoop (see 30 // MessageLoop::task_runner()). 31 // - Create their own worker thread and MessageLoop to post tasks to. 32 // - Add tasks to a FIFO and signal to a non-MessageLoop thread for them to 33 // be processed. This allows TaskRunner-oriented code run on threads 34 // running other kinds of message loop, e.g. Jingle threads. 35 class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner { 36 public: 37 // A more explicit alias to RunsTasksInCurrentSequence(). BelongsToCurrentThread()38 bool BelongsToCurrentThread() const { return RunsTasksInCurrentSequence(); } 39 40 // Returns the default SingleThreadTaskRunner for the current thread. 41 // On threads that service multiple task queues, the default task queue is 42 // preferred to inheriting the current task queue (otherwise, everything would 43 // implicitly be "input priority"...). If the caller knows which task queue it 44 // should be running on, it should post to that SingleThreadTaskRunner 45 // directly instead of GetCurrentDefault(). This is critical in some 46 // cases, e.g. DeleteSoon or RefCountedDeleteOnSequence should delete the 47 // object on the same task queue it's used from (or on a lower priority). 48 // 49 // DCHECKs if the current thread isn't servicing a SingleThreadTaskRunner. 50 // 51 // See 52 // https://chromium.googlesource.com/chromium/src/+/main/docs/threading_and_tasks.md#Posting-to-the-Current-Virtual_Thread 53 // for details 54 55 [[nodiscard]] static const scoped_refptr<SingleThreadTaskRunner>& 56 GetCurrentDefault(); 57 58 // Returns true if the SingleThreadTaskRunner is already created for 59 // the current thread. 60 [[nodiscard]] static bool HasCurrentDefault(); 61 62 class CurrentHandleOverride; 63 class CurrentHandleOverrideForTesting; 64 65 class BASE_EXPORT CurrentDefaultHandle { 66 public: 67 // Binds |task_runner| to the current thread. |task_runner| must belong 68 // to the current thread. 69 explicit CurrentDefaultHandle( 70 scoped_refptr<SingleThreadTaskRunner> task_runner); 71 72 CurrentDefaultHandle(const CurrentDefaultHandle&) = delete; 73 CurrentDefaultHandle& operator=(const CurrentDefaultHandle&) = delete; 74 75 ~CurrentDefaultHandle(); 76 77 private: 78 friend class SingleThreadTaskRunner; 79 friend class CurrentHandleOverride; 80 81 const AutoReset<CurrentDefaultHandle*> resetter_; 82 83 scoped_refptr<SingleThreadTaskRunner> task_runner_; 84 85 // Registers |task_runner_|'s SequencedTaskRunner interface as the 86 // SequencedTaskRunner::CurrentDefaultHandle on this thread. 87 SequencedTaskRunner::CurrentDefaultHandle 88 sequenced_task_runner_current_default_; 89 }; 90 91 // CurrentHandleOverride overrides the task runner returned by 92 // |SingleThreadTaskRunner::GetCurrentDefault()| to point at 93 // |overriding_task_runner| until the |CurrentHandleOverride| goes out of 94 // scope. CurrentHandleOverride instantiates a new SingleThreadTaskRunner if 95 // SingleThreadTaskRunner is not instantiated on the current thread. Nested 96 // overrides are allowed but callers must ensure the |CurrentHandleOverride|s 97 // expire in LIFO (stack) order. 98 // 99 // Note: nesting SingleThreadTaskRunner is subtle and should be done with 100 // care, hence the need to friend and request a //base/OWNERS review for usage 101 // outside of tests. Use CurrentHandleOverrideForTesting to bypass the friend 102 // requirement in tests. 103 class BASE_EXPORT CurrentHandleOverride { 104 public: 105 CurrentHandleOverride(const CurrentHandleOverride&) = delete; 106 CurrentHandleOverride& operator=(const CurrentHandleOverride&) = delete; 107 ~CurrentHandleOverride(); 108 109 private: 110 friend class CurrentHandleOverrideForTesting; 111 FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, 112 NestedRunLoop); 113 114 // We expect SingleThreadTaskRunner::CurrentHandleOverride to be only needed 115 // under special circumstances. Require them to be enumerated as friends to 116 // require //base/OWNERS review. Use 117 // SingleTaskRunner::CurrentHandleOverrideForTesting in unit tests to avoid 118 // the friend requirement. 119 120 friend class blink::scheduler::MainThreadSchedulerImpl; 121 122 // Constructs a SingleThreadTaskRunner::CurrentHandleOverride which will 123 // make SingleThreadTaskRunner::GetCurrentDefault() return 124 // |overriding_task_runner| for its lifetime. |allow_nested_loop| specifies 125 // whether RunLoop::Run() is allowed during this override's lifetime. It's 126 // not recommended to allow this unless the current thread's scheduler 127 // guarantees that only tasks which pertain to |overriding_task_runner|'s 128 // context will be run by nested RunLoops. 129 explicit CurrentHandleOverride( 130 scoped_refptr<SingleThreadTaskRunner> overriding_task_runner, 131 bool allow_nested_runloop = false); 132 133 absl::optional<SingleThreadTaskRunner::CurrentDefaultHandle> 134 top_level_thread_task_runner_current_default_; 135 136 scoped_refptr<SingleThreadTaskRunner> task_runner_to_restore_; 137 138 #if DCHECK_IS_ON() 139 // This field is not a raw_ptr<> because it was filtered by the rewriter 140 // for: #union 141 RAW_PTR_EXCLUSION SingleThreadTaskRunner* 142 expected_task_runner_before_restore_{nullptr}; 143 #endif 144 145 std::unique_ptr<ScopedDisallowRunningRunLoop> no_running_during_override_; 146 }; 147 148 // Note: nesting CurrentHandleOverrides isn't generally desired but it's 149 // useful in some unit tests where multiple task runners share the main thread 150 // for simplicity and determinism. Only use this when no other constructs will 151 // work (see base/test/task_environment.h and 152 // base/test/test_mock_time_task_runner.h for preferred alternatives). 153 class BASE_EXPORT CurrentHandleOverrideForTesting { 154 public: CurrentHandleOverrideForTesting(scoped_refptr<SingleThreadTaskRunner> overriding_task_runner)155 explicit CurrentHandleOverrideForTesting( 156 scoped_refptr<SingleThreadTaskRunner> overriding_task_runner) 157 : thread_task_runner_current_override_( 158 std::move(overriding_task_runner)) {} 159 160 private: 161 CurrentHandleOverride thread_task_runner_current_override_; 162 }; 163 164 protected: 165 ~SingleThreadTaskRunner() override = default; 166 }; 167 168 } // namespace base 169 170 #endif // BASE_TASK_SINGLE_THREAD_TASK_RUNNER_H_ 171