xref: /aosp_15_r20/external/cronet/base/run_loop.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_RUN_LOOP_H_
6*6777b538SAndroid Build Coastguard Worker #define BASE_RUN_LOOP_H_
7*6777b538SAndroid Build Coastguard Worker 
8*6777b538SAndroid Build Coastguard Worker #include <stack>
9*6777b538SAndroid Build Coastguard Worker #include <utility>
10*6777b538SAndroid Build Coastguard Worker #include <vector>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/containers/stack.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/gtest_prod_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/memory/weak_ptr.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/observer_list.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/sequence_checker.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
24*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
25*6777b538SAndroid Build Coastguard Worker 
26*6777b538SAndroid Build Coastguard Worker namespace base {
27*6777b538SAndroid Build Coastguard Worker 
28*6777b538SAndroid Build Coastguard Worker namespace test {
29*6777b538SAndroid Build Coastguard Worker class ScopedRunLoopTimeout;
30*6777b538SAndroid Build Coastguard Worker class ScopedDisableRunLoopTimeout;
31*6777b538SAndroid Build Coastguard Worker }  // namespace test
32*6777b538SAndroid Build Coastguard Worker 
33*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
34*6777b538SAndroid Build Coastguard Worker class MessagePumpAndroid;
35*6777b538SAndroid Build Coastguard Worker #endif
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
38*6777b538SAndroid Build Coastguard Worker class MessagePumpUIApplication;
39*6777b538SAndroid Build Coastguard Worker #endif
40*6777b538SAndroid Build Coastguard Worker 
41*6777b538SAndroid Build Coastguard Worker class SingleThreadTaskRunner;
42*6777b538SAndroid Build Coastguard Worker 
43*6777b538SAndroid Build Coastguard Worker // Helper class to run the RunLoop::Delegate associated with the current thread.
44*6777b538SAndroid Build Coastguard Worker // A RunLoop::Delegate must have been bound to this thread (ref.
45*6777b538SAndroid Build Coastguard Worker // RunLoop::RegisterDelegateForCurrentThread()) prior to using any of RunLoop's
46*6777b538SAndroid Build Coastguard Worker // member and static methods unless explicitly indicated otherwise (e.g.
47*6777b538SAndroid Build Coastguard Worker // IsRunning/IsNestedOnCurrentThread()). RunLoop::Run can only be called once
48*6777b538SAndroid Build Coastguard Worker // per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run
49*6777b538SAndroid Build Coastguard Worker // a nested RunLoop but please avoid nested loops in production code!
50*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT RunLoop {
51*6777b538SAndroid Build Coastguard Worker  public:
52*6777b538SAndroid Build Coastguard Worker   // The type of RunLoop: a kDefault RunLoop at the top-level (non-nested) will
53*6777b538SAndroid Build Coastguard Worker   // process system and application tasks assigned to its Delegate. When nested
54*6777b538SAndroid Build Coastguard Worker   // however a kDefault RunLoop will only process system tasks while a
55*6777b538SAndroid Build Coastguard Worker   // kNestableTasksAllowed RunLoop will continue to process application tasks
56*6777b538SAndroid Build Coastguard Worker   // even if nested.
57*6777b538SAndroid Build Coastguard Worker   //
58*6777b538SAndroid Build Coastguard Worker   // This is relevant in the case of recursive RunLoops. Some unwanted run loops
59*6777b538SAndroid Build Coastguard Worker   // may occur when using common controls or printer functions. By default,
60*6777b538SAndroid Build Coastguard Worker   // recursive task processing is disabled.
61*6777b538SAndroid Build Coastguard Worker   //
62*6777b538SAndroid Build Coastguard Worker   // In general, nestable RunLoops are to be avoided. They are dangerous and
63*6777b538SAndroid Build Coastguard Worker   // difficult to get right, so please use with extreme caution.
64*6777b538SAndroid Build Coastguard Worker   //
65*6777b538SAndroid Build Coastguard Worker   // A specific example where this makes a difference is:
66*6777b538SAndroid Build Coastguard Worker   // - The thread is running a RunLoop.
67*6777b538SAndroid Build Coastguard Worker   // - It receives a task #1 and executes it.
68*6777b538SAndroid Build Coastguard Worker   // - The task #1 implicitly starts a RunLoop, like a MessageBox in the unit
69*6777b538SAndroid Build Coastguard Worker   //   test. This can also be StartDoc or GetSaveFileName.
70*6777b538SAndroid Build Coastguard Worker   // - The thread receives a task #2 before or while in this second RunLoop.
71*6777b538SAndroid Build Coastguard Worker   // - With a kNestableTasksAllowed RunLoop, the task #2 will run right away.
72*6777b538SAndroid Build Coastguard Worker   //   Otherwise, it will get executed right after task #1 completes in the main
73*6777b538SAndroid Build Coastguard Worker   //   RunLoop.
74*6777b538SAndroid Build Coastguard Worker   enum class Type {
75*6777b538SAndroid Build Coastguard Worker     kDefault,
76*6777b538SAndroid Build Coastguard Worker     kNestableTasksAllowed,
77*6777b538SAndroid Build Coastguard Worker   };
78*6777b538SAndroid Build Coastguard Worker 
79*6777b538SAndroid Build Coastguard Worker   explicit RunLoop(Type type = Type::kDefault);
80*6777b538SAndroid Build Coastguard Worker   RunLoop(const RunLoop&) = delete;
81*6777b538SAndroid Build Coastguard Worker   RunLoop& operator=(const RunLoop&) = delete;
82*6777b538SAndroid Build Coastguard Worker   ~RunLoop();
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker   // Run the current RunLoop::Delegate. This blocks until Quit is called
85*6777b538SAndroid Build Coastguard Worker   // (directly or by running the RunLoop::QuitClosure).
86*6777b538SAndroid Build Coastguard Worker   void Run(const Location& location = Location::Current());
87*6777b538SAndroid Build Coastguard Worker 
88*6777b538SAndroid Build Coastguard Worker   // Run the current RunLoop::Delegate until it doesn't find any tasks or
89*6777b538SAndroid Build Coastguard Worker   // messages in its queue (it goes idle).
90*6777b538SAndroid Build Coastguard Worker   // WARNING #1: This may run long (flakily timeout) and even never return! Do
91*6777b538SAndroid Build Coastguard Worker   //             not use this when repeating tasks such as animated web pages
92*6777b538SAndroid Build Coastguard Worker   //             are present.
93*6777b538SAndroid Build Coastguard Worker   // WARNING #2: This may return too early! For example, if used to run until an
94*6777b538SAndroid Build Coastguard Worker   //             incoming event has occurred but that event depends on a task in
95*6777b538SAndroid Build Coastguard Worker   //             a different queue -- e.g. another TaskRunner or a system event.
96*6777b538SAndroid Build Coastguard Worker   // Per the warnings above, this tends to lead to flaky tests; prefer
97*6777b538SAndroid Build Coastguard Worker   // QuitClosure()+Run() when at all possible.
98*6777b538SAndroid Build Coastguard Worker   void RunUntilIdle();
99*6777b538SAndroid Build Coastguard Worker 
running()100*6777b538SAndroid Build Coastguard Worker   bool running() const {
101*6777b538SAndroid Build Coastguard Worker     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
102*6777b538SAndroid Build Coastguard Worker     return running_;
103*6777b538SAndroid Build Coastguard Worker   }
104*6777b538SAndroid Build Coastguard Worker 
105*6777b538SAndroid Build Coastguard Worker   // Quit() transitions this RunLoop to a state where no more tasks will be
106*6777b538SAndroid Build Coastguard Worker   // allowed to run at the run-loop-level of this RunLoop. If invoked from the
107*6777b538SAndroid Build Coastguard Worker   // owning thread, the effect is immediate; otherwise it is thread-safe but
108*6777b538SAndroid Build Coastguard Worker   // asynchronous. When the transition takes effect, the underlying message loop
109*6777b538SAndroid Build Coastguard Worker   // quits this run-loop-level if it is topmost (otherwise the desire to quit
110*6777b538SAndroid Build Coastguard Worker   // this level is saved until run-levels nested above it are quit).
111*6777b538SAndroid Build Coastguard Worker   //
112*6777b538SAndroid Build Coastguard Worker   // QuitWhenIdle() results in this RunLoop returning true from
113*6777b538SAndroid Build Coastguard Worker   // ShouldQuitWhenIdle() at this run-level (the delegate decides when "idle" is
114*6777b538SAndroid Build Coastguard Worker   // reached). This is also thread-safe.
115*6777b538SAndroid Build Coastguard Worker   //
116*6777b538SAndroid Build Coastguard Worker   // There can be other nested RunLoops servicing the same task queue. As
117*6777b538SAndroid Build Coastguard Worker   // mentioned above, quitting one RunLoop has no bearing on the others. Hence,
118*6777b538SAndroid Build Coastguard Worker   // you may never assume that a call to Quit() will terminate the underlying
119*6777b538SAndroid Build Coastguard Worker   // message loop. If a nested RunLoop continues running, the target may NEVER
120*6777b538SAndroid Build Coastguard Worker   // terminate.
121*6777b538SAndroid Build Coastguard Worker   void Quit();
122*6777b538SAndroid Build Coastguard Worker   void QuitWhenIdle();
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker   // Returns a RepeatingClosure that safely calls Quit() or QuitWhenIdle() (has
125*6777b538SAndroid Build Coastguard Worker   // no effect if the RunLoop instance is gone).
126*6777b538SAndroid Build Coastguard Worker   //
127*6777b538SAndroid Build Coastguard Worker   // The closures must be obtained from the thread owning the RunLoop but may
128*6777b538SAndroid Build Coastguard Worker   // then be invoked from any thread.
129*6777b538SAndroid Build Coastguard Worker   //
130*6777b538SAndroid Build Coastguard Worker   // Returned closures may be safely:
131*6777b538SAndroid Build Coastguard Worker   //   * Passed to other threads.
132*6777b538SAndroid Build Coastguard Worker   //   * Run() from other threads, though this will quit the RunLoop
133*6777b538SAndroid Build Coastguard Worker   //     asynchronously.
134*6777b538SAndroid Build Coastguard Worker   //   * Run() after the RunLoop has stopped or been destroyed, in which case
135*6777b538SAndroid Build Coastguard Worker   //     they are a no-op).
136*6777b538SAndroid Build Coastguard Worker   //   * Run() before RunLoop::Run(), in which case RunLoop::Run() returns
137*6777b538SAndroid Build Coastguard Worker   //     immediately."
138*6777b538SAndroid Build Coastguard Worker   //
139*6777b538SAndroid Build Coastguard Worker   // Example:
140*6777b538SAndroid Build Coastguard Worker   //   RunLoop run_loop;
141*6777b538SAndroid Build Coastguard Worker   //   DoFooAsyncAndNotify(run_loop.QuitClosure());
142*6777b538SAndroid Build Coastguard Worker   //   run_loop.Run();
143*6777b538SAndroid Build Coastguard Worker   //
144*6777b538SAndroid Build Coastguard Worker   // Note that Quit() itself is thread-safe and may be invoked directly if you
145*6777b538SAndroid Build Coastguard Worker   // have access to the RunLoop reference from another thread (e.g. from a
146*6777b538SAndroid Build Coastguard Worker   // capturing lambda or test observer).
147*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] RepeatingClosure QuitClosure();
148*6777b538SAndroid Build Coastguard Worker   [[nodiscard]] RepeatingClosure QuitWhenIdleClosure();
149*6777b538SAndroid Build Coastguard Worker 
150*6777b538SAndroid Build Coastguard Worker   // Returns true if Quit() or QuitWhenIdle() was called.
151*6777b538SAndroid Build Coastguard Worker   bool AnyQuitCalled();
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker   // Returns true if there is an active RunLoop on this thread.
154*6777b538SAndroid Build Coastguard Worker   // Safe to call before RegisterDelegateForCurrentThread().
155*6777b538SAndroid Build Coastguard Worker   static bool IsRunningOnCurrentThread();
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker   // Returns true if there is an active RunLoop on this thread and it's nested
158*6777b538SAndroid Build Coastguard Worker   // within another active RunLoop.
159*6777b538SAndroid Build Coastguard Worker   // Safe to call before RegisterDelegateForCurrentThread().
160*6777b538SAndroid Build Coastguard Worker   static bool IsNestedOnCurrentThread();
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker   // A NestingObserver is notified when a nested RunLoop begins and ends.
163*6777b538SAndroid Build Coastguard Worker   class BASE_EXPORT NestingObserver {
164*6777b538SAndroid Build Coastguard Worker    public:
165*6777b538SAndroid Build Coastguard Worker     // Notified before a nested loop starts running work on the current thread.
166*6777b538SAndroid Build Coastguard Worker     virtual void OnBeginNestedRunLoop() = 0;
167*6777b538SAndroid Build Coastguard Worker     // Notified after a nested loop is done running work on the current thread.
OnExitNestedRunLoop()168*6777b538SAndroid Build Coastguard Worker     virtual void OnExitNestedRunLoop() {}
169*6777b538SAndroid Build Coastguard Worker 
170*6777b538SAndroid Build Coastguard Worker    protected:
171*6777b538SAndroid Build Coastguard Worker     virtual ~NestingObserver() = default;
172*6777b538SAndroid Build Coastguard Worker   };
173*6777b538SAndroid Build Coastguard Worker 
174*6777b538SAndroid Build Coastguard Worker   static void AddNestingObserverOnCurrentThread(NestingObserver* observer);
175*6777b538SAndroid Build Coastguard Worker   static void RemoveNestingObserverOnCurrentThread(NestingObserver* observer);
176*6777b538SAndroid Build Coastguard Worker 
177*6777b538SAndroid Build Coastguard Worker   // A RunLoop::Delegate is a generic interface that allows RunLoop to be
178*6777b538SAndroid Build Coastguard Worker   // separate from the underlying implementation of the message loop for this
179*6777b538SAndroid Build Coastguard Worker   // thread. It holds private state used by RunLoops on its associated thread.
180*6777b538SAndroid Build Coastguard Worker   // One and only one RunLoop::Delegate must be registered on a given thread
181*6777b538SAndroid Build Coastguard Worker   // via RunLoop::RegisterDelegateForCurrentThread() before RunLoop instances
182*6777b538SAndroid Build Coastguard Worker   // and RunLoop static methods can be used on it.
183*6777b538SAndroid Build Coastguard Worker   class BASE_EXPORT Delegate {
184*6777b538SAndroid Build Coastguard Worker    public:
185*6777b538SAndroid Build Coastguard Worker     Delegate();
186*6777b538SAndroid Build Coastguard Worker     Delegate(const Delegate&) = delete;
187*6777b538SAndroid Build Coastguard Worker     Delegate& operator=(const Delegate&) = delete;
188*6777b538SAndroid Build Coastguard Worker     virtual ~Delegate();
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker     // Used by RunLoop to inform its Delegate to Run/Quit. Implementations are
191*6777b538SAndroid Build Coastguard Worker     // expected to keep on running synchronously from the Run() call until the
192*6777b538SAndroid Build Coastguard Worker     // eventual matching Quit() call or a delay of |timeout| expires. Upon
193*6777b538SAndroid Build Coastguard Worker     // receiving a Quit() call or timing out it should return from the Run()
194*6777b538SAndroid Build Coastguard Worker     // call as soon as possible without executing remaining tasks/messages.
195*6777b538SAndroid Build Coastguard Worker     // Run() calls can nest in which case each Quit() call should result in the
196*6777b538SAndroid Build Coastguard Worker     // topmost active Run() call returning. The only other trigger for Run()
197*6777b538SAndroid Build Coastguard Worker     // to return is the |should_quit_when_idle_callback_| which the Delegate
198*6777b538SAndroid Build Coastguard Worker     // should probe before sleeping when it becomes idle.
199*6777b538SAndroid Build Coastguard Worker     // |application_tasks_allowed| is true if this is the first Run() call on
200*6777b538SAndroid Build Coastguard Worker     // the stack or it was made from a nested RunLoop of
201*6777b538SAndroid Build Coastguard Worker     // Type::kNestableTasksAllowed (otherwise this Run() level should only
202*6777b538SAndroid Build Coastguard Worker     // process system tasks).
203*6777b538SAndroid Build Coastguard Worker     virtual void Run(bool application_tasks_allowed, TimeDelta timeout) = 0;
204*6777b538SAndroid Build Coastguard Worker     virtual void Quit() = 0;
205*6777b538SAndroid Build Coastguard Worker 
206*6777b538SAndroid Build Coastguard Worker     // Invoked right before a RunLoop enters a nested Run() call on this
207*6777b538SAndroid Build Coastguard Worker     // Delegate iff this RunLoop is of type kNestableTasksAllowed. The Delegate
208*6777b538SAndroid Build Coastguard Worker     // should ensure that the upcoming Run() call will result in processing
209*6777b538SAndroid Build Coastguard Worker     // application tasks queued ahead of it without further probing. e.g.
210*6777b538SAndroid Build Coastguard Worker     // message pumps on some platforms, like Mac, need an explicit request to
211*6777b538SAndroid Build Coastguard Worker     // process application tasks when nested, otherwise they'll only wait for
212*6777b538SAndroid Build Coastguard Worker     // system messages.
213*6777b538SAndroid Build Coastguard Worker     virtual void EnsureWorkScheduled() = 0;
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker    protected:
216*6777b538SAndroid Build Coastguard Worker     // Returns the result of this Delegate's |should_quit_when_idle_callback_|.
217*6777b538SAndroid Build Coastguard Worker     // "protected" so it can be invoked only by the Delegate itself. The
218*6777b538SAndroid Build Coastguard Worker     // Delegate is expected to quit Run() if this returns true.
219*6777b538SAndroid Build Coastguard Worker     bool ShouldQuitWhenIdle();
220*6777b538SAndroid Build Coastguard Worker 
221*6777b538SAndroid Build Coastguard Worker    private:
222*6777b538SAndroid Build Coastguard Worker     // While the state is owned by the Delegate subclass, only RunLoop can use
223*6777b538SAndroid Build Coastguard Worker     // it.
224*6777b538SAndroid Build Coastguard Worker     friend class RunLoop;
225*6777b538SAndroid Build Coastguard Worker 
226*6777b538SAndroid Build Coastguard Worker     friend class ScopedDisallowRunningRunLoop;
227*6777b538SAndroid Build Coastguard Worker 
228*6777b538SAndroid Build Coastguard Worker     // A vector-based stack is more memory efficient than the default
229*6777b538SAndroid Build Coastguard Worker     // deque-based stack as the active RunLoop stack isn't expected to ever
230*6777b538SAndroid Build Coastguard Worker     // have more than a few entries.
231*6777b538SAndroid Build Coastguard Worker     using RunLoopStack =
232*6777b538SAndroid Build Coastguard Worker         stack<raw_ptr<RunLoop, VectorExperimental>,
233*6777b538SAndroid Build Coastguard Worker               std::vector<raw_ptr<RunLoop, VectorExperimental>>>;
234*6777b538SAndroid Build Coastguard Worker 
235*6777b538SAndroid Build Coastguard Worker     RunLoopStack active_run_loops_;
236*6777b538SAndroid Build Coastguard Worker     ObserverList<RunLoop::NestingObserver>::Unchecked nesting_observers_;
237*6777b538SAndroid Build Coastguard Worker 
238*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
239*6777b538SAndroid Build Coastguard Worker     bool allow_running_for_testing_ = true;
240*6777b538SAndroid Build Coastguard Worker #endif
241*6777b538SAndroid Build Coastguard Worker 
242*6777b538SAndroid Build Coastguard Worker     // True once this Delegate is bound to a thread via
243*6777b538SAndroid Build Coastguard Worker     // RegisterDelegateForCurrentThread().
244*6777b538SAndroid Build Coastguard Worker     bool bound_ = false;
245*6777b538SAndroid Build Coastguard Worker 
246*6777b538SAndroid Build Coastguard Worker     // Thread-affine per its use of TLS.
247*6777b538SAndroid Build Coastguard Worker     THREAD_CHECKER(bound_thread_checker_);
248*6777b538SAndroid Build Coastguard Worker   };
249*6777b538SAndroid Build Coastguard Worker 
250*6777b538SAndroid Build Coastguard Worker   // Registers |delegate| on the current thread. Must be called once and only
251*6777b538SAndroid Build Coastguard Worker   // once per thread before using RunLoop methods on it. |delegate| is from then
252*6777b538SAndroid Build Coastguard Worker   // on forever bound to that thread (including its destruction).
253*6777b538SAndroid Build Coastguard Worker   static void RegisterDelegateForCurrentThread(Delegate* new_delegate);
254*6777b538SAndroid Build Coastguard Worker 
255*6777b538SAndroid Build Coastguard Worker   // Support for //base/test/scoped_run_loop_timeout.h.
256*6777b538SAndroid Build Coastguard Worker   // This must be public for access by the implementation code in run_loop.cc.
257*6777b538SAndroid Build Coastguard Worker   struct BASE_EXPORT RunLoopTimeout {
258*6777b538SAndroid Build Coastguard Worker     RunLoopTimeout();
259*6777b538SAndroid Build Coastguard Worker     ~RunLoopTimeout();
260*6777b538SAndroid Build Coastguard Worker     TimeDelta timeout;
261*6777b538SAndroid Build Coastguard Worker     RepeatingCallback<void(const Location&)> on_timeout;
262*6777b538SAndroid Build Coastguard Worker   };
263*6777b538SAndroid Build Coastguard Worker 
264*6777b538SAndroid Build Coastguard Worker  private:
265*6777b538SAndroid Build Coastguard Worker   FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskExecutorTypedTest,
266*6777b538SAndroid Build Coastguard Worker                            RunLoopQuitOrderAfter);
267*6777b538SAndroid Build Coastguard Worker 
268*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_ANDROID)
269*6777b538SAndroid Build Coastguard Worker   // Android doesn't support the blocking RunLoop::Run, so it calls
270*6777b538SAndroid Build Coastguard Worker   // BeforeRun and AfterRun directly.
271*6777b538SAndroid Build Coastguard Worker   friend class MessagePumpAndroid;
272*6777b538SAndroid Build Coastguard Worker #endif
273*6777b538SAndroid Build Coastguard Worker 
274*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_IOS)
275*6777b538SAndroid Build Coastguard Worker   // iOS doesn't support the blocking RunLoop::Run, so it calls
276*6777b538SAndroid Build Coastguard Worker   // BeforeRun directly.
277*6777b538SAndroid Build Coastguard Worker   friend class MessagePumpUIApplication;
278*6777b538SAndroid Build Coastguard Worker #endif
279*6777b538SAndroid Build Coastguard Worker 
280*6777b538SAndroid Build Coastguard Worker   // Support for //base/test/scoped_run_loop_timeout.h.
281*6777b538SAndroid Build Coastguard Worker   friend class test::ScopedRunLoopTimeout;
282*6777b538SAndroid Build Coastguard Worker   friend class test::ScopedDisableRunLoopTimeout;
283*6777b538SAndroid Build Coastguard Worker 
284*6777b538SAndroid Build Coastguard Worker   static void SetTimeoutForCurrentThread(const RunLoopTimeout* timeout);
285*6777b538SAndroid Build Coastguard Worker   static const RunLoopTimeout* GetTimeoutForCurrentThread();
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   // Return false to abort the Run.
288*6777b538SAndroid Build Coastguard Worker   bool BeforeRun();
289*6777b538SAndroid Build Coastguard Worker   void AfterRun();
290*6777b538SAndroid Build Coastguard Worker 
291*6777b538SAndroid Build Coastguard Worker   // A cached reference of RunLoop::Delegate for the thread driven by this
292*6777b538SAndroid Build Coastguard Worker   // RunLoop for quick access without using TLS (also allows access to state
293*6777b538SAndroid Build Coastguard Worker   // from another sequence during Run(), ref. |sequence_checker_| below).
294*6777b538SAndroid Build Coastguard Worker   const raw_ptr<Delegate, DanglingUntriaged> delegate_;
295*6777b538SAndroid Build Coastguard Worker 
296*6777b538SAndroid Build Coastguard Worker   const Type type_;
297*6777b538SAndroid Build Coastguard Worker 
298*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
299*6777b538SAndroid Build Coastguard Worker   bool run_allowed_ = true;
300*6777b538SAndroid Build Coastguard Worker #endif
301*6777b538SAndroid Build Coastguard Worker 
302*6777b538SAndroid Build Coastguard Worker   bool quit_called_ = false;
303*6777b538SAndroid Build Coastguard Worker   bool running_ = false;
304*6777b538SAndroid Build Coastguard Worker 
305*6777b538SAndroid Build Coastguard Worker   // Used to record that QuitWhenIdle() was called on this RunLoop.
306*6777b538SAndroid Build Coastguard Worker   bool quit_when_idle_called_ = false;
307*6777b538SAndroid Build Coastguard Worker   // Whether the Delegate should quit Run() once it becomes idle (it's
308*6777b538SAndroid Build Coastguard Worker   // responsible for probing this state via ShouldQuitWhenIdle()). This state is
309*6777b538SAndroid Build Coastguard Worker   // stored here rather than pushed to Delegate to support nested RunLoops.
310*6777b538SAndroid Build Coastguard Worker   bool quit_when_idle_ = false;
311*6777b538SAndroid Build Coastguard Worker 
312*6777b538SAndroid Build Coastguard Worker   // RunLoop is not thread-safe. Its state/methods, unless marked as such, may
313*6777b538SAndroid Build Coastguard Worker   // not be accessed from any other sequence than the thread it was constructed
314*6777b538SAndroid Build Coastguard Worker   // on. Exception: RunLoop can be safely accessed from one other sequence (or
315*6777b538SAndroid Build Coastguard Worker   // single parallel task) during Run() -- e.g. to Quit() without having to
316*6777b538SAndroid Build Coastguard Worker   // plumb SingleThreadTaskRunner::GetCurrentDefault() throughout a test to
317*6777b538SAndroid Build Coastguard Worker   // repost QuitClosure to origin thread.
318*6777b538SAndroid Build Coastguard Worker   SEQUENCE_CHECKER(sequence_checker_);
319*6777b538SAndroid Build Coastguard Worker 
320*6777b538SAndroid Build Coastguard Worker   const scoped_refptr<SingleThreadTaskRunner> origin_task_runner_;
321*6777b538SAndroid Build Coastguard Worker 
322*6777b538SAndroid Build Coastguard Worker   // WeakPtrFactory for QuitClosure safety.
323*6777b538SAndroid Build Coastguard Worker   WeakPtrFactory<RunLoop> weak_factory_{this};
324*6777b538SAndroid Build Coastguard Worker };
325*6777b538SAndroid Build Coastguard Worker 
326*6777b538SAndroid Build Coastguard Worker // RunLoop::Run() will DCHECK if called while there's a
327*6777b538SAndroid Build Coastguard Worker // ScopedDisallowRunningRunLoop in scope on its thread. This is useful to add
328*6777b538SAndroid Build Coastguard Worker // safety to some test constructs which allow multiple task runners to share the
329*6777b538SAndroid Build Coastguard Worker // main thread in unit tests. While the main thread can be shared by multiple
330*6777b538SAndroid Build Coastguard Worker // runners to deterministically fake multi threading, there can still only be a
331*6777b538SAndroid Build Coastguard Worker // single RunLoop::Delegate per thread and RunLoop::Run() should only be invoked
332*6777b538SAndroid Build Coastguard Worker // from it (or it would result in incorrectly driving TaskRunner A while in
333*6777b538SAndroid Build Coastguard Worker // TaskRunner B's context).
334*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedDisallowRunningRunLoop {
335*6777b538SAndroid Build Coastguard Worker  public:
336*6777b538SAndroid Build Coastguard Worker   ScopedDisallowRunningRunLoop();
337*6777b538SAndroid Build Coastguard Worker   ScopedDisallowRunningRunLoop(const ScopedDisallowRunningRunLoop&) = delete;
338*6777b538SAndroid Build Coastguard Worker   ScopedDisallowRunningRunLoop& operator=(const ScopedDisallowRunningRunLoop&) =
339*6777b538SAndroid Build Coastguard Worker       delete;
340*6777b538SAndroid Build Coastguard Worker   ~ScopedDisallowRunningRunLoop();
341*6777b538SAndroid Build Coastguard Worker 
342*6777b538SAndroid Build Coastguard Worker  private:
343*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
344*6777b538SAndroid Build Coastguard Worker   raw_ptr<RunLoop::Delegate> current_delegate_;
345*6777b538SAndroid Build Coastguard Worker   const bool previous_run_allowance_;
346*6777b538SAndroid Build Coastguard Worker #endif  // DCHECK_IS_ON()
347*6777b538SAndroid Build Coastguard Worker };
348*6777b538SAndroid Build Coastguard Worker 
349*6777b538SAndroid Build Coastguard Worker }  // namespace base
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker #endif  // BASE_RUN_LOOP_H_
352