blob: 077d097ba9a2a35c6ec51d017f588b9f195e48c0 [file] [log] [blame]
Daniel Eratb8cf9492015-07-06 13:18:13 -06001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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_RUN_LOOP_H_
6#define BASE_RUN_LOOP_H_
7
8#include "base/base_export.h"
9#include "base/callback.h"
Alex Vakulenko0d205d72016-01-15 13:02:14 -080010#include "base/macros.h"
Daniel Eratb8cf9492015-07-06 13:18:13 -060011#include "base/memory/weak_ptr.h"
12#include "base/message_loop/message_loop.h"
Jay Civelli3a83cdd2017-03-22 17:31:44 -070013#include "base/threading/thread_checker.h"
Alex Vakulenko0d205d72016-01-15 13:02:14 -080014#include "build/build_config.h"
Daniel Eratb8cf9492015-07-06 13:18:13 -060015
16namespace base {
17#if defined(OS_ANDROID)
18class MessagePumpForUI;
19#endif
20
Daniel Eratb8cf9492015-07-06 13:18:13 -060021#if defined(OS_IOS)
22class MessagePumpUIApplication;
23#endif
24
25// Helper class to Run a nested MessageLoop. Please do not use nested
26// MessageLoops in production code! If you must, use this class instead of
27// calling MessageLoop::Run/Quit directly. RunLoop::Run can only be called once
28// per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run
29// a nested MessageLoop.
30class BASE_EXPORT RunLoop {
31 public:
32 RunLoop();
Daniel Eratb8cf9492015-07-06 13:18:13 -060033 ~RunLoop();
34
35 // Run the current MessageLoop. This blocks until Quit is called. Before
Alex Vakulenko45779222016-03-17 10:36:19 -070036 // calling Run, be sure to grab the QuitClosure in order to stop the
37 // MessageLoop asynchronously. MessageLoop::QuitWhenIdle and QuitNow will also
38 // trigger a return from Run, but those are deprecated.
Daniel Eratb8cf9492015-07-06 13:18:13 -060039 void Run();
40
41 // Run the current MessageLoop until it doesn't find any tasks or messages in
42 // the queue (it goes idle). WARNING: This may never return! Only use this
43 // when repeating tasks such as animated web pages have been shut down.
44 void RunUntilIdle();
45
46 bool running() const { return running_; }
47
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -070048 // Quit() quits an earlier call to Run() immediately. QuitWhenIdle() quits an
49 // earlier call to Run() when there aren't any tasks or messages in the queue.
Daniel Eratb8cf9492015-07-06 13:18:13 -060050 //
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -070051 // There can be other nested RunLoops servicing the same task queue
52 // (MessageLoop); Quitting one RunLoop has no bearing on the others. Quit()
53 // and QuitWhenIdle() can be called before, during or after Run(). If called
54 // before Run(), Run() will return immediately when called. Calling Quit() or
55 // QuitWhenIdle() after the RunLoop has already finished running has no
56 // effect.
57 //
58 // WARNING: You must NEVER assume that a call to Quit() or QuitWhenIdle() will
59 // terminate the targetted message loop. If a nested message loop continues
60 // running, the target may NEVER terminate. It is very easy to livelock (run
61 // forever) in such a case.
Daniel Eratb8cf9492015-07-06 13:18:13 -060062 void Quit();
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -070063 void QuitWhenIdle();
Daniel Eratb8cf9492015-07-06 13:18:13 -060064
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -070065 // Convenience methods to get a closure that safely calls Quit() or
66 // QuitWhenIdle() (has no effect if the RunLoop instance is gone).
Daniel Eratb8cf9492015-07-06 13:18:13 -060067 //
68 // Example:
69 // RunLoop run_loop;
70 // PostTask(run_loop.QuitClosure());
71 // run_loop.Run();
72 base::Closure QuitClosure();
Luis Hector Chavez0c4f26a2016-07-15 16:23:21 -070073 base::Closure QuitWhenIdleClosure();
Daniel Eratb8cf9492015-07-06 13:18:13 -060074
75 private:
76 friend class MessageLoop;
77#if defined(OS_ANDROID)
78 // Android doesn't support the blocking MessageLoop::Run, so it calls
79 // BeforeRun and AfterRun directly.
80 friend class base::MessagePumpForUI;
81#endif
82
83#if defined(OS_IOS)
84 // iOS doesn't support the blocking MessageLoop::Run, so it calls
85 // BeforeRun directly.
86 friend class base::MessagePumpUIApplication;
87#endif
88
89 // Return false to abort the Run.
90 bool BeforeRun();
91 void AfterRun();
92
93 MessageLoop* loop_;
94
95 // Parent RunLoop or NULL if this is the top-most RunLoop.
96 RunLoop* previous_run_loop_;
97
Daniel Eratb8cf9492015-07-06 13:18:13 -060098 // Used to count how many nested Run() invocations are on the stack.
99 int run_depth_;
100
101 bool run_called_;
102 bool quit_called_;
103 bool running_;
104
105 // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning
106 // that we should quit Run once it becomes idle.
107 bool quit_when_idle_received_;
108
Jay Civelli3a83cdd2017-03-22 17:31:44 -0700109 base::ThreadChecker thread_checker_;
110
Daniel Eratb8cf9492015-07-06 13:18:13 -0600111 // WeakPtrFactory for QuitClosure safety.
112 base::WeakPtrFactory<RunLoop> weak_factory_;
113
114 DISALLOW_COPY_AND_ASSIGN(RunLoop);
115};
116
117} // namespace base
118
119#endif // BASE_RUN_LOOP_H_