OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_RUN_LOOP_H_ | 5 #ifndef BASE_RUN_LOOP_H_ |
6 #define BASE_RUN_LOOP_H_ | 6 #define BASE_RUN_LOOP_H_ |
7 | 7 |
| 8 #include <stack> |
| 9 #include <vector> |
| 10 |
8 #include "base/base_export.h" | 11 #include "base/base_export.h" |
9 #include "base/callback.h" | 12 #include "base/callback.h" |
10 #include "base/macros.h" | 13 #include "base/macros.h" |
11 #include "base/memory/weak_ptr.h" | 14 #include "base/memory/weak_ptr.h" |
12 #include "base/message_loop/message_loop.h" | 15 #include "base/observer_list.h" |
13 #include "base/threading/thread_checker.h" | 16 #include "base/threading/thread_checker.h" |
14 #include "build/build_config.h" | 17 #include "build/build_config.h" |
15 | 18 |
16 namespace base { | 19 namespace base { |
17 #if defined(OS_ANDROID) | 20 #if defined(OS_ANDROID) |
18 class MessagePumpForUI; | 21 class MessagePumpForUI; |
19 #endif | 22 #endif |
20 | 23 |
21 #if defined(OS_IOS) | 24 #if defined(OS_IOS) |
22 class MessagePumpUIApplication; | 25 class MessagePumpUIApplication; |
23 #endif | 26 #endif |
24 | 27 |
25 // Helper class to Run a nested MessageLoop. Please do not use nested | 28 // Helper class to run the RunLoop::Delegate associated with the current thread. |
26 // MessageLoops in production code! If you must, use this class instead of | 29 // A RunLoop::Delegate must have been bound to this thread (ref. |
27 // calling MessageLoop::Run/Quit directly. RunLoop::Run can only be called once | 30 // RunLoop::RegisterDelegateForCurrentThread()) prior to using any of RunLoop's |
| 31 // member and static methods unless explicitly indicated otherwise (e.g. |
| 32 // IsRunning/IsNestedOnCurrentThread()). RunLoop::Run can only be called once |
28 // per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run | 33 // per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run |
29 // a nested MessageLoop. | 34 // a nested RunLoop but please do not use nested loops in production code! |
30 class BASE_EXPORT RunLoop { | 35 class BASE_EXPORT RunLoop { |
31 public: | 36 public: |
32 RunLoop(); | 37 RunLoop(); |
33 ~RunLoop(); | 38 ~RunLoop(); |
34 | 39 |
35 // Run the current MessageLoop. This blocks until Quit is called. Before | 40 // Run the current RunLoop::Delegate. This blocks until Quit is called. Before |
36 // calling Run, be sure to grab the QuitClosure in order to stop the | 41 // calling Run, be sure to grab the QuitClosure in order to stop the |
37 // MessageLoop asynchronously. MessageLoop::QuitWhenIdle and QuitNow will also | 42 // RunLoop::Delegate asynchronously. MessageLoop::QuitWhenIdle and QuitNow |
38 // trigger a return from Run, but those are deprecated. | 43 // will also trigger a return from Run (if RunLoop::Delegate happens to be a |
| 44 // MessageLoop...), but those are deprecated. |
39 void Run(); | 45 void Run(); |
40 | 46 |
41 // Run the current MessageLoop until it doesn't find any tasks or messages in | 47 // Run the current RunLoop::Delegate until it doesn't find any tasks or |
42 // the queue (it goes idle). WARNING: This may never return! Only use this | 48 // messages in its queue (it goes idle). WARNING: This may never return! Only |
43 // when repeating tasks such as animated web pages have been shut down. | 49 // use this when repeating tasks such as animated web pages have been shut |
| 50 // down. |
44 void RunUntilIdle(); | 51 void RunUntilIdle(); |
45 | 52 |
46 bool running() const { | 53 bool running() const { |
47 // TODO(gab): Fix bad usage and enable this check, http://crbug.com/715235. | 54 // TODO(gab): Fix bad usage and enable this check, http://crbug.com/715235. |
48 // DCHECK(thread_checker_.CalledOnValidThread()); | 55 // DCHECK(thread_checker_.CalledOnValidThread()); |
49 return running_; | 56 return running_; |
50 } | 57 } |
51 | 58 |
52 // Quit() quits an earlier call to Run() immediately. QuitWhenIdle() quits an | 59 // Quit() quits an earlier call to Run() immediately. QuitWhenIdle() quits an |
53 // earlier call to Run() when there aren't any tasks or messages in the queue. | 60 // earlier call to Run() when there aren't any tasks or messages in the queue. |
(...skipping 15 matching lines...) Expand all Loading... |
69 // Convenience methods to get a closure that safely calls Quit() or | 76 // Convenience methods to get a closure that safely calls Quit() or |
70 // QuitWhenIdle() (has no effect if the RunLoop instance is gone). | 77 // QuitWhenIdle() (has no effect if the RunLoop instance is gone). |
71 // | 78 // |
72 // Example: | 79 // Example: |
73 // RunLoop run_loop; | 80 // RunLoop run_loop; |
74 // PostTask(run_loop.QuitClosure()); | 81 // PostTask(run_loop.QuitClosure()); |
75 // run_loop.Run(); | 82 // run_loop.Run(); |
76 base::Closure QuitClosure(); | 83 base::Closure QuitClosure(); |
77 base::Closure QuitWhenIdleClosure(); | 84 base::Closure QuitWhenIdleClosure(); |
78 | 85 |
79 // Cleans pre-existing TLS state. | |
80 // TODO(gab): Remove this in favor of managing TLS through RunLoop::Delegate | |
81 // as part of the RunLoop<=>MessageLoop split in http://crbug.com/703346. | |
82 static void ResetTLSState(); | |
83 | |
84 // Returns true if there is an active RunLoop on this thread. | 86 // Returns true if there is an active RunLoop on this thread. |
| 87 // Safe to call before RegisterDelegateForCurrentThread(). |
85 static bool IsRunningOnCurrentThread(); | 88 static bool IsRunningOnCurrentThread(); |
86 | 89 |
87 // Returns true if there is an active RunLoop on this thread and it's nested | 90 // Returns true if there is an active RunLoop on this thread and it's nested |
88 // within another active RunLoop. | 91 // within another active RunLoop. |
| 92 // Safe to call before RegisterDelegateForCurrentThread(). |
89 static bool IsNestedOnCurrentThread(); | 93 static bool IsNestedOnCurrentThread(); |
90 | 94 |
91 // A NestingObserver is notified when a nested run loop begins. The observers | 95 // A NestingObserver is notified when a nested run loop begins. The observers |
92 // are notified before the current thread's RunLoop::Delegate::Run() is | 96 // are notified before the current thread's RunLoop::Delegate::Run() is |
93 // invoked and nested work begins. | 97 // invoked and nested work begins. |
94 class BASE_EXPORT NestingObserver { | 98 class BASE_EXPORT NestingObserver { |
95 public: | 99 public: |
96 virtual void OnBeginNestedRunLoop() = 0; | 100 virtual void OnBeginNestedRunLoop() = 0; |
97 | 101 |
98 protected: | 102 protected: |
99 virtual ~NestingObserver() = default; | 103 virtual ~NestingObserver() = default; |
100 }; | 104 }; |
101 | 105 |
102 static void AddNestingObserverOnCurrentThread(NestingObserver* observer); | 106 static void AddNestingObserverOnCurrentThread(NestingObserver* observer); |
103 static void RemoveNestingObserverOnCurrentThread(NestingObserver* observer); | 107 static void RemoveNestingObserverOnCurrentThread(NestingObserver* observer); |
104 | 108 |
105 // Returns true if nesting is allowed on this thread. | 109 // Returns true if nesting is allowed on this thread. |
106 static bool IsNestingAllowedOnCurrentThread(); | 110 static bool IsNestingAllowedOnCurrentThread(); |
107 | 111 |
108 // Disallow nesting. After this is called, running a nested RunLoop or calling | 112 // Disallow nesting. After this is called, running a nested RunLoop or calling |
109 // Add/RemoveNestingObserverOnCurrentThread() on this thread will crash. | 113 // Add/RemoveNestingObserverOnCurrentThread() on this thread will crash. |
110 static void DisallowNestingOnCurrentThread(); | 114 static void DisallowNestingOnCurrentThread(); |
111 | 115 |
| 116 // A RunLoop::Delegate is a generic interface that allows RunLoop to be |
| 117 // separate from the uderlying implementation of the message loop for this |
| 118 // thread. It holds private state used by RunLoops on its associated thread. |
| 119 // One and only one RunLoop::Delegate must be registered on a given thread |
| 120 // via RunLoop::RegisterDelegateForCurrentThread() before RunLoop instances |
| 121 // and RunLoop static methods can be used on it. |
| 122 class BASE_EXPORT Delegate { |
| 123 protected: |
| 124 Delegate(); |
| 125 ~Delegate(); |
| 126 |
| 127 // The client interface provided back to the caller who registers this |
| 128 // Delegate via RegisterDelegateForCurrentThread. |
| 129 class Client { |
| 130 public: |
| 131 // Returns the RunLoop with the topmost active Run() call on the stack. |
| 132 // TODO(gab): Break the inter-dependency between MessageLoop and RunLoop |
| 133 // further. http://crbug.com/703346 |
| 134 RunLoop* GetTopMostRunLoop() const; |
| 135 |
| 136 // Returns true if this |outer_| is currently in nested runs. This is a |
| 137 // shortcut for RunLoop::IsNestedOnCurrentThread() for the owner of this |
| 138 // interface. |
| 139 // TODO(gab): consider getting rid of this and the Client class altogether |
| 140 // when it's the only method left on Client. http://crbug.com/703346. |
| 141 bool IsNested() const; |
| 142 |
| 143 private: |
| 144 // Only a Delegate can instantiate a Delegate::Client. |
| 145 friend class Delegate; |
| 146 Client(Delegate* outer); |
| 147 |
| 148 Delegate* outer_; |
| 149 }; |
| 150 |
| 151 private: |
| 152 // While the state is owned by the Delegate subclass, only RunLoop can use |
| 153 // it. |
| 154 friend class RunLoop; |
| 155 |
| 156 // Used by RunLoop to inform its Delegate to Run/Quit. Implementations are |
| 157 // expected to keep on running synchronously from the Run() call until the |
| 158 // eventual matching Quit() call. Upon receiving a Quit() call it should |
| 159 // return from the Run() call as soon as possible without executing |
| 160 // remaining tasks/messages. Run() calls can nest in which case each Quit() |
| 161 // call should result in the topmost active Run() call returning. |
| 162 virtual void Run() = 0; |
| 163 virtual void Quit() = 0; |
| 164 |
| 165 // A vector-based stack is more memory efficient than the default |
| 166 // deque-based stack as the active RunLoop stack isn't expected to ever |
| 167 // have more than a few entries. |
| 168 using RunLoopStack = std::stack<RunLoop*, std::vector<RunLoop*>>; |
| 169 |
| 170 bool allow_nesting_ = true; |
| 171 RunLoopStack active_run_loops_; |
| 172 ObserverList<RunLoop::NestingObserver> nesting_observers_; |
| 173 |
| 174 // True once this Delegate is bound to a thread via |
| 175 // RegisterDelegateForCurrentThread(). |
| 176 bool bound_ = false; |
| 177 |
| 178 THREAD_CHECKER(bound_thread_checker_); |
| 179 |
| 180 Client client_interface_ = Client(this); |
| 181 |
| 182 DISALLOW_COPY_AND_ASSIGN(Delegate); |
| 183 }; |
| 184 |
| 185 // Registers |delegate| on the current thread. Must be called once and only |
| 186 // once per thread before using RunLoop methods on it. |delegate| is from then |
| 187 // on forever bound to that thread (including its destruction). The returned |
| 188 // Delegate::Client is valid as long as |delegate| is kept alive. |
| 189 static Delegate::Client* RegisterDelegateForCurrentThread(Delegate* delegate); |
| 190 |
112 private: | 191 private: |
| 192 // TODO(gab): Break the inter-dependency between MessageLoop and RunLoop |
| 193 // further. http://crbug.com/703346 |
113 friend class MessageLoop; | 194 friend class MessageLoop; |
114 #if defined(OS_ANDROID) | 195 #if defined(OS_ANDROID) |
115 // Android doesn't support the blocking MessageLoop::Run, so it calls | 196 // Android doesn't support the blocking MessageLoop::Run, so it calls |
116 // BeforeRun and AfterRun directly. | 197 // BeforeRun and AfterRun directly. |
117 friend class base::MessagePumpForUI; | 198 friend class base::MessagePumpForUI; |
118 #endif | 199 #endif |
119 | 200 |
120 #if defined(OS_IOS) | 201 #if defined(OS_IOS) |
121 // iOS doesn't support the blocking MessageLoop::Run, so it calls | 202 // iOS doesn't support the blocking MessageLoop::Run, so it calls |
122 // BeforeRun directly. | 203 // BeforeRun directly. |
123 friend class base::MessagePumpUIApplication; | 204 friend class base::MessagePumpUIApplication; |
124 #endif | 205 #endif |
125 | 206 |
126 // Return false to abort the Run. | 207 // Return false to abort the Run. |
127 bool BeforeRun(); | 208 bool BeforeRun(); |
128 void AfterRun(); | 209 void AfterRun(); |
129 | 210 |
130 MessageLoop* loop_; | 211 // A copy of RunLoop::Delegate for this thread for quick access without using |
| 212 // TLS. |
| 213 Delegate* delegate_; |
131 | 214 |
132 bool run_called_ = false; | 215 bool run_called_ = false; |
133 bool quit_called_ = false; | 216 bool quit_called_ = false; |
134 bool running_ = false; | 217 bool running_ = false; |
135 | 218 |
136 // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning | 219 // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning |
137 // that we should quit Run once it becomes idle. | 220 // that we should quit Run once it becomes idle. |
138 bool quit_when_idle_received_ = false; | 221 bool quit_when_idle_received_ = false; |
139 | 222 |
140 // RunLoop's non-static methods are affine to the thread it's running on per | 223 // RunLoop's non-static methods are affine to the thread it's running on per |
141 // this class' underlying use of thread-local-storage. | 224 // this class' underlying use of thread-local-storage. |
142 base::ThreadChecker thread_checker_; | 225 base::ThreadChecker thread_checker_; |
143 | 226 |
144 // WeakPtrFactory for QuitClosure safety. | 227 // WeakPtrFactory for QuitClosure safety. |
145 base::WeakPtrFactory<RunLoop> weak_factory_; | 228 base::WeakPtrFactory<RunLoop> weak_factory_; |
146 | 229 |
147 DISALLOW_COPY_AND_ASSIGN(RunLoop); | 230 DISALLOW_COPY_AND_ASSIGN(RunLoop); |
148 }; | 231 }; |
149 | 232 |
150 } // namespace base | 233 } // namespace base |
151 | 234 |
152 #endif // BASE_RUN_LOOP_H_ | 235 #endif // BASE_RUN_LOOP_H_ |
OLD | NEW |