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 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" 10 #include "base/macros.h" 11 #include "base/memory/weak_ptr.h" 12 #include "base/message_loop/message_loop.h" 13 #include "base/threading/thread_checker.h" 14 #include "build/build_config.h" 15 16 namespace base { 17 #if defined(OS_ANDROID) 18 class MessagePumpForUI; 19 #endif 20 21 #if defined(OS_IOS) 22 class 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. 30 class BASE_EXPORT RunLoop { 31 public: 32 RunLoop(); 33 ~RunLoop(); 34 35 // Run the current MessageLoop. This blocks until Quit is called. Before 36 // 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. 39 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 48 // 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. 50 // 51 // 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. 62 void Quit(); 63 void QuitWhenIdle(); 64 65 // Convenience methods to get a closure that safely calls Quit() or 66 // QuitWhenIdle() (has no effect if the RunLoop instance is gone). 67 // 68 // Example: 69 // RunLoop run_loop; 70 // PostTask(run_loop.QuitClosure()); 71 // run_loop.Run(); 72 base::Closure QuitClosure(); 73 base::Closure QuitWhenIdleClosure(); 74 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 98 // 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 109 base::ThreadChecker thread_checker_; 110 111 // 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_ 120