blob: 93c38e4405f001b0fafd83f15225bed23c13e64a [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
[email protected]8e937c1e2012-06-28 22:57:302// 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_RUN_LOOP_H_
6#define BASE_RUN_LOOP_H_
[email protected]8e937c1e2012-06-28 22:57:307
Gabriel Charette1ef212b2017-12-03 12:47:218#include <utility>
gab273551962017-05-18 06:01:109#include <vector>
10
[email protected]8e937c1e2012-06-28 22:57:3011#include "base/base_export.h"
Brett Wilson1f07f20e2017-10-02 18:55:2812#include "base/containers/stack.h"
Gabriel Charette2a53350172021-05-06 20:22:5513#include "base/dcheck_is_on.h"
Avi Drissman63e1f992023-01-13 18:54:4314#include "base/functional/callback.h"
Wez9d5dd282020-02-10 17:21:2215#include "base/gtest_prod_util.h"
danakje125e8d62021-01-21 22:06:3116#include "base/location.h"
Keishi Hattorie175ac52022-06-07 06:24:5717#include "base/memory/raw_ptr.h"
[email protected]8e937c1e2012-06-28 22:57:3018#include "base/memory/weak_ptr.h"
gab273551962017-05-18 06:01:1019#include "base/observer_list.h"
gab980a52712017-05-18 16:20:1620#include "base/sequence_checker.h"
ahest72c1b442016-12-09 20:40:3821#include "base/threading/thread_checker.h"
Wezd9e4cb772019-01-09 03:07:0322#include "base/time/time.h"
avi9b6f42932015-12-26 22:15:1423#include "build/build_config.h"
[email protected]8e937c1e2012-06-28 22:57:3024
25namespace base {
Wez9d5dd282020-02-10 17:21:2226
27namespace test {
28class ScopedRunLoopTimeout;
29class ScopedDisableRunLoopTimeout;
30} // namespace test
31
Xiaohan Wang38e4ebb2022-01-19 06:57:4332#if BUILDFLAG(IS_ANDROID)
Egor Pasko6da5a07c2024-03-11 19:56:2933class MessagePumpAndroid;
[email protected]8e937c1e2012-06-28 22:57:3034#endif
35
Xiaohan Wang38e4ebb2022-01-19 06:57:4336#if BUILDFLAG(IS_IOS)
[email protected]feb727e2012-07-13 11:02:5737class MessagePumpUIApplication;
38#endif
39
gabcf5e4ce2017-05-19 22:56:5740class SingleThreadTaskRunner;
41
gab273551962017-05-18 06:01:1042// Helper class to run the RunLoop::Delegate associated with the current thread.
43// A RunLoop::Delegate must have been bound to this thread (ref.
44// RunLoop::RegisterDelegateForCurrentThread()) prior to using any of RunLoop's
45// member and static methods unless explicitly indicated otherwise (e.g.
46// IsRunning/IsNestedOnCurrentThread()). RunLoop::Run can only be called once
[email protected]8e937c1e2012-06-28 22:57:3047// per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run
Gabriel Charette3a2ce022020-05-28 19:44:3548// a nested RunLoop but please avoid nested loops in production code!
[email protected]8e937c1e2012-06-28 22:57:3049class BASE_EXPORT RunLoop {
50 public:
Gabriel Charette3ff403e2017-08-07 04:22:4851 // The type of RunLoop: a kDefault RunLoop at the top-level (non-nested) will
52 // process system and application tasks assigned to its Delegate. When nested
53 // however a kDefault RunLoop will only process system tasks while a
54 // kNestableTasksAllowed RunLoop will continue to process application tasks
55 // even if nested.
56 //
57 // This is relevant in the case of recursive RunLoops. Some unwanted run loops
58 // may occur when using common controls or printer functions. By default,
59 // recursive task processing is disabled.
60 //
61 // In general, nestable RunLoops are to be avoided. They are dangerous and
Gabriel Charetted8839442018-03-15 18:56:2262 // difficult to get right, so please use with extreme caution.
Gabriel Charette3ff403e2017-08-07 04:22:4863 //
64 // A specific example where this makes a difference is:
65 // - The thread is running a RunLoop.
66 // - It receives a task #1 and executes it.
67 // - The task #1 implicitly starts a RunLoop, like a MessageBox in the unit
68 // test. This can also be StartDoc or GetSaveFileName.
69 // - The thread receives a task #2 before or while in this second RunLoop.
70 // - With a kNestableTasksAllowed RunLoop, the task #2 will run right away.
71 // Otherwise, it will get executed right after task #1 completes in the main
72 // RunLoop.
73 enum class Type {
74 kDefault,
75 kNestableTasksAllowed,
76 };
77
David Bienvenu5f4d4f02020-09-27 16:55:0378 explicit RunLoop(Type type = Type::kDefault);
79 RunLoop(const RunLoop&) = delete;
80 RunLoop& operator=(const RunLoop&) = delete;
[email protected]8e937c1e2012-06-28 22:57:3081 ~RunLoop();
82
Gabriel Charette3a2ce022020-05-28 19:44:3583 // Run the current RunLoop::Delegate. This blocks until Quit is called
84 // (directly or by running the RunLoop::QuitClosure).
danakje125e8d62021-01-21 22:06:3185 void Run(const Location& location = Location::Current());
[email protected]8e937c1e2012-06-28 22:57:3086
gab273551962017-05-18 06:01:1087 // Run the current RunLoop::Delegate until it doesn't find any tasks or
Gabriel Charette69ab2e02019-01-15 15:41:0588 // messages in its queue (it goes idle).
Gabriel Charette76a55342019-01-16 00:26:1189 // WARNING #1: This may run long (flakily timeout) and even never return! Do
90 // not use this when repeating tasks such as animated web pages
91 // are present.
Gabriel Charette69ab2e02019-01-15 15:41:0592 // WARNING #2: This may return too early! For example, if used to run until an
93 // incoming event has occurred but that event depends on a task in
Gabriel Charettebd9c67b2019-03-20 15:22:3494 // a different queue -- e.g. another TaskRunner or a system event.
95 // Per the warnings above, this tends to lead to flaky tests; prefer
Gabriel Charette69ab2e02019-01-15 15:41:0596 // QuitClosure()+Run() when at all possible.
[email protected]8e937c1e2012-06-28 22:57:3097 void RunUntilIdle();
98
gab7af9dc02017-05-05 13:38:5499 bool running() const {
gab980a52712017-05-18 16:20:16100 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
gab7af9dc02017-05-05 13:38:54101 return running_;
102 }
[email protected]8e937c1e2012-06-28 22:57:30103
Gabriel Charette3a2ce022020-05-28 19:44:35104 // Quit() transitions this RunLoop to a state where no more tasks will be
105 // allowed to run at the run-loop-level of this RunLoop. If invoked from the
106 // owning thread, the effect is immediate; otherwise it is thread-safe but
107 // asynchronous. When the transition takes effect, the underlying message loop
108 // quits this run-loop-level if it is topmost (otherwise the desire to quit
109 // this level is saved until run-levels nested above it are quit).
[email protected]8e937c1e2012-06-28 22:57:30110 //
Gabriel Charette3a2ce022020-05-28 19:44:35111 // QuitWhenIdle() results in this RunLoop returning true from
112 // ShouldQuitWhenIdle() at this run-level (the delegate decides when "idle" is
113 // reached). This is also thread-safe.
gabcf5e4ce2017-05-19 22:56:57114 //
Gabriel Charette3a2ce022020-05-28 19:44:35115 // There can be other nested RunLoops servicing the same task queue. As
116 // mentioned above, quitting one RunLoop has no bearing on the others. Hence,
117 // you may never assume that a call to Quit() will terminate the underlying
118 // message loop. If a nested RunLoop continues running, the target may NEVER
119 // terminate.
[email protected]8e937c1e2012-06-28 22:57:30120 void Quit();
fdoraya4f28ec2016-06-10 00:08:58121 void QuitWhenIdle();
[email protected]8e937c1e2012-06-28 22:57:30122
kylechar650caf02019-07-17 03:25:41123 // Returns a RepeatingClosure that safely calls Quit() or QuitWhenIdle() (has
124 // no effect if the RunLoop instance is gone).
[email protected]8e937c1e2012-06-28 22:57:30125 //
Gabriel Charette3a2ce022020-05-28 19:44:35126 // The closures must be obtained from the thread owning the RunLoop but may
127 // then be invoked from any thread.
Gabriel Charetted913e5b2019-06-27 05:41:59128 //
kylechar650caf02019-07-17 03:25:41129 // Returned closures may be safely:
Gabriel Charetted913e5b2019-06-27 05:41:59130 // * Passed to other threads.
131 // * Run() from other threads, though this will quit the RunLoop
132 // asynchronously.
133 // * Run() after the RunLoop has stopped or been destroyed, in which case
134 // they are a no-op).
135 // * Run() before RunLoop::Run(), in which case RunLoop::Run() returns
136 // immediately."
gabcf5e4ce2017-05-19 22:56:57137 //
[email protected]8e937c1e2012-06-28 22:57:30138 // Example:
139 // RunLoop run_loop;
Gabriel Charetted913e5b2019-06-27 05:41:59140 // DoFooAsyncAndNotify(run_loop.QuitClosure());
[email protected]8e937c1e2012-06-28 22:57:30141 // run_loop.Run();
Gabriel Charetted913e5b2019-06-27 05:41:59142 //
143 // Note that Quit() itself is thread-safe and may be invoked directly if you
144 // have access to the RunLoop reference from another thread (e.g. from a
145 // capturing lambda or test observer).
Peter Kasting0bc6a682024-09-09 09:38:34146 [[nodiscard]] RepeatingClosure QuitClosure() &;
147 [[nodiscard]] RepeatingClosure QuitWhenIdleClosure() &;
[email protected]8e937c1e2012-06-28 22:57:30148
Gabriel Charette2a53350172021-05-06 20:22:55149 // Returns true if Quit() or QuitWhenIdle() was called.
150 bool AnyQuitCalled();
151
gab7af9dc02017-05-05 13:38:54152 // Returns true if there is an active RunLoop on this thread.
gab273551962017-05-18 06:01:10153 // Safe to call before RegisterDelegateForCurrentThread().
gab7af9dc02017-05-05 13:38:54154 static bool IsRunningOnCurrentThread();
155
156 // Returns true if there is an active RunLoop on this thread and it's nested
157 // within another active RunLoop.
gab273551962017-05-18 06:01:10158 // Safe to call before RegisterDelegateForCurrentThread().
gab7af9dc02017-05-05 13:38:54159 static bool IsNestedOnCurrentThread();
160
Francois Doray80bdddf2018-01-04 16:17:32161 // A NestingObserver is notified when a nested RunLoop begins and ends.
gab7af9dc02017-05-05 13:38:54162 class BASE_EXPORT NestingObserver {
163 public:
Francois Doray80bdddf2018-01-04 16:17:32164 // Notified before a nested loop starts running work on the current thread.
gab7af9dc02017-05-05 13:38:54165 virtual void OnBeginNestedRunLoop() = 0;
Francois Doray80bdddf2018-01-04 16:17:32166 // Notified after a nested loop is done running work on the current thread.
167 virtual void OnExitNestedRunLoop() {}
gab7af9dc02017-05-05 13:38:54168
169 protected:
170 virtual ~NestingObserver() = default;
171 };
172
173 static void AddNestingObserverOnCurrentThread(NestingObserver* observer);
174 static void RemoveNestingObserverOnCurrentThread(NestingObserver* observer);
175
gab273551962017-05-18 06:01:10176 // A RunLoop::Delegate is a generic interface that allows RunLoop to be
Gabriel Charettea3ec9612017-12-14 17:22:40177 // separate from the underlying implementation of the message loop for this
gab273551962017-05-18 06:01:10178 // thread. It holds private state used by RunLoops on its associated thread.
179 // One and only one RunLoop::Delegate must be registered on a given thread
180 // via RunLoop::RegisterDelegateForCurrentThread() before RunLoop instances
181 // and RunLoop static methods can be used on it.
182 class BASE_EXPORT Delegate {
Gabriel Charette46c535d22017-12-03 12:14:01183 public:
gab273551962017-05-18 06:01:10184 Delegate();
David Bienvenu5f4d4f02020-09-27 16:55:03185 Delegate(const Delegate&) = delete;
186 Delegate& operator=(const Delegate&) = delete;
Gabriel Charette1ef212b2017-12-03 12:47:21187 virtual ~Delegate();
gab273551962017-05-18 06:01:10188
gab273551962017-05-18 06:01:10189 // Used by RunLoop to inform its Delegate to Run/Quit. Implementations are
190 // expected to keep on running synchronously from the Run() call until the
Alex Clarke9752bbf2019-04-01 10:41:20191 // eventual matching Quit() call or a delay of |timeout| expires. Upon
192 // receiving a Quit() call or timing out it should return from the Run()
193 // call as soon as possible without executing remaining tasks/messages.
194 // Run() calls can nest in which case each Quit() call should result in the
195 // topmost active Run() call returning. The only other trigger for Run()
196 // to return is the |should_quit_when_idle_callback_| which the Delegate
197 // should probe before sleeping when it becomes idle.
198 // |application_tasks_allowed| is true if this is the first Run() call on
199 // the stack or it was made from a nested RunLoop of
200 // Type::kNestableTasksAllowed (otherwise this Run() level should only
201 // process system tasks).
202 virtual void Run(bool application_tasks_allowed, TimeDelta timeout) = 0;
gab273551962017-05-18 06:01:10203 virtual void Quit() = 0;
204
Gabriel Charette3ff403e2017-08-07 04:22:48205 // Invoked right before a RunLoop enters a nested Run() call on this
206 // Delegate iff this RunLoop is of type kNestableTasksAllowed. The Delegate
207 // should ensure that the upcoming Run() call will result in processing
208 // application tasks queued ahead of it without further probing. e.g.
209 // message pumps on some platforms, like Mac, need an explicit request to
210 // process application tasks when nested, otherwise they'll only wait for
211 // system messages.
212 virtual void EnsureWorkScheduled() = 0;
213
Gabriel Charettea3ec9612017-12-14 17:22:40214 protected:
215 // Returns the result of this Delegate's |should_quit_when_idle_callback_|.
Gabriel Charettefbf3c622020-11-19 14:51:13216 // "protected" so it can be invoked only by the Delegate itself. The
217 // Delegate is expected to quit Run() if this returns true.
Gabriel Charettea3ec9612017-12-14 17:22:40218 bool ShouldQuitWhenIdle();
219
Gabriel Charette46c535d22017-12-03 12:14:01220 private:
221 // While the state is owned by the Delegate subclass, only RunLoop can use
222 // it.
223 friend class RunLoop;
224
Hans Wennborg9b292ba2022-02-15 16:01:29225 friend class ScopedDisallowRunningRunLoop;
226
gab273551962017-05-18 06:01:10227 // A vector-based stack is more memory efficient than the default
228 // deque-based stack as the active RunLoop stack isn't expected to ever
229 // have more than a few entries.
Ali Hijazie63cbaf62023-12-20 19:29:35230 using RunLoopStack =
231 stack<raw_ptr<RunLoop, VectorExperimental>,
232 std::vector<raw_ptr<RunLoop, VectorExperimental>>>;
gab273551962017-05-18 06:01:10233
gab273551962017-05-18 06:01:10234 RunLoopStack active_run_loops_;
Trent Apteda250ec3ab2018-08-19 08:52:19235 ObserverList<RunLoop::NestingObserver>::Unchecked nesting_observers_;
gab273551962017-05-18 06:01:10236
Gabriel Charettea44975052017-08-21 23:14:04237#if DCHECK_IS_ON()
238 bool allow_running_for_testing_ = true;
239#endif
240
gab273551962017-05-18 06:01:10241 // True once this Delegate is bound to a thread via
242 // RegisterDelegateForCurrentThread().
243 bool bound_ = false;
244
gab980a52712017-05-18 16:20:16245 // Thread-affine per its use of TLS.
gab273551962017-05-18 06:01:10246 THREAD_CHECKER(bound_thread_checker_);
gab273551962017-05-18 06:01:10247 };
248
249 // Registers |delegate| on the current thread. Must be called once and only
250 // once per thread before using RunLoop methods on it. |delegate| is from then
Gabriel Charettea3ec9612017-12-14 17:22:40251 // on forever bound to that thread (including its destruction).
Peter Kasting960e2d32023-03-14 17:18:41252 static void RegisterDelegateForCurrentThread(Delegate* new_delegate);
gab273551962017-05-18 06:01:10253
Wez9d5dd282020-02-10 17:21:22254 // Support for //base/test/scoped_run_loop_timeout.h.
255 // This must be public for access by the implementation code in run_loop.cc.
256 struct BASE_EXPORT RunLoopTimeout {
257 RunLoopTimeout();
258 ~RunLoopTimeout();
259 TimeDelta timeout;
danakje125e8d62021-01-21 22:06:31260 RepeatingCallback<void(const Location&)> on_timeout;
Wez9d5dd282020-02-10 17:21:22261 };
262
[email protected]8e937c1e2012-06-28 22:57:30263 private:
Carlos Caballero40b6d042020-06-16 06:50:25264 FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskExecutorTypedTest,
265 RunLoopQuitOrderAfter);
Wez325eafc2018-07-17 17:01:49266
Xiaohan Wang38e4ebb2022-01-19 06:57:43267#if BUILDFLAG(IS_ANDROID)
Gabriel Charettee2b632b2017-08-02 03:52:16268 // Android doesn't support the blocking RunLoop::Run, so it calls
[email protected]8e937c1e2012-06-28 22:57:30269 // BeforeRun and AfterRun directly.
Egor Pasko6da5a07c2024-03-11 19:56:29270 friend class MessagePumpAndroid;
[email protected]8e937c1e2012-06-28 22:57:30271#endif
272
Xiaohan Wang38e4ebb2022-01-19 06:57:43273#if BUILDFLAG(IS_IOS)
Gabriel Charettee2b632b2017-08-02 03:52:16274 // iOS doesn't support the blocking RunLoop::Run, so it calls
[email protected]feb727e2012-07-13 11:02:57275 // BeforeRun directly.
Wezd9e4cb772019-01-09 03:07:03276 friend class MessagePumpUIApplication;
[email protected]feb727e2012-07-13 11:02:57277#endif
278
Wez9d5dd282020-02-10 17:21:22279 // Support for //base/test/scoped_run_loop_timeout.h.
280 friend class test::ScopedRunLoopTimeout;
281 friend class test::ScopedDisableRunLoopTimeout;
282
283 static void SetTimeoutForCurrentThread(const RunLoopTimeout* timeout);
284 static const RunLoopTimeout* GetTimeoutForCurrentThread();
285
[email protected]8e937c1e2012-06-28 22:57:30286 // Return false to abort the Run.
287 bool BeforeRun();
288 void AfterRun();
289
Gabriel Charetteb87279d2019-06-27 03:21:04290 // A cached reference of RunLoop::Delegate for the thread driven by this
291 // RunLoop for quick access without using TLS (also allows access to state
292 // from another sequence during Run(), ref. |sequence_checker_| below).
Bartek Nowierskif5eeeba2024-01-25 12:49:39293 const raw_ptr<Delegate, DanglingUntriaged> delegate_;
[email protected]8e937c1e2012-06-28 22:57:30294
Gabriel Charette3ff403e2017-08-07 04:22:48295 const Type type_;
296
gabcf5e4ce2017-05-19 22:56:57297#if DCHECK_IS_ON()
Gabriel Charette2a53350172021-05-06 20:22:55298 bool run_allowed_ = true;
gabcf5e4ce2017-05-19 22:56:57299#endif
300
gab7af9dc02017-05-05 13:38:54301 bool quit_called_ = false;
302 bool running_ = false;
Gabriel Charette2a53350172021-05-06 20:22:55303
304 // Used to record that QuitWhenIdle() was called on this RunLoop.
305 bool quit_when_idle_called_ = false;
306 // Whether the Delegate should quit Run() once it becomes idle (it's
307 // responsible for probing this state via ShouldQuitWhenIdle()). This state is
308 // stored here rather than pushed to Delegate to support nested RunLoops.
309 bool quit_when_idle_ = false;
[email protected]8e937c1e2012-06-28 22:57:30310
gabcf5e4ce2017-05-19 22:56:57311 // RunLoop is not thread-safe. Its state/methods, unless marked as such, may
312 // not be accessed from any other sequence than the thread it was constructed
313 // on. Exception: RunLoop can be safely accessed from one other sequence (or
314 // single parallel task) during Run() -- e.g. to Quit() without having to
Sean Mahere672a662023-01-09 21:42:28315 // plumb SingleThreadTaskRunner::GetCurrentDefault() throughout a test to
316 // repost QuitClosure to origin thread.
gab980a52712017-05-18 16:20:16317 SEQUENCE_CHECKER(sequence_checker_);
ahest72c1b442016-12-09 20:40:38318
gabcf5e4ce2017-05-19 22:56:57319 const scoped_refptr<SingleThreadTaskRunner> origin_task_runner_;
320
[email protected]dcf10632013-10-08 19:23:33321 // WeakPtrFactory for QuitClosure safety.
Jeremy Roman577d88492019-07-05 14:30:23322 WeakPtrFactory<RunLoop> weak_factory_{this};
[email protected]8e937c1e2012-06-28 22:57:30323};
324
Hans Wennborg9b292ba2022-02-15 16:01:29325// RunLoop::Run() will DCHECK if called while there's a
326// ScopedDisallowRunningRunLoop in scope on its thread. This is useful to add
327// safety to some test constructs which allow multiple task runners to share the
328// main thread in unit tests. While the main thread can be shared by multiple
329// runners to deterministically fake multi threading, there can still only be a
330// single RunLoop::Delegate per thread and RunLoop::Run() should only be invoked
331// from it (or it would result in incorrectly driving TaskRunner A while in
332// TaskRunner B's context).
Peter Kasting960e2d32023-03-14 17:18:41333class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedDisallowRunningRunLoop {
Hans Wennborg9b292ba2022-02-15 16:01:29334 public:
335 ScopedDisallowRunningRunLoop();
336 ScopedDisallowRunningRunLoop(const ScopedDisallowRunningRunLoop&) = delete;
337 ScopedDisallowRunningRunLoop& operator=(const ScopedDisallowRunningRunLoop&) =
338 delete;
339 ~ScopedDisallowRunningRunLoop();
340
341 private:
342#if DCHECK_IS_ON()
Keishi Hattorie175ac52022-06-07 06:24:57343 raw_ptr<RunLoop::Delegate> current_delegate_;
Hans Wennborg9b292ba2022-02-15 16:01:29344 const bool previous_run_allowance_;
345#endif // DCHECK_IS_ON()
346};
347
[email protected]8e937c1e2012-06-28 22:57:30348} // namespace base
349
350#endif // BASE_RUN_LOOP_H_