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