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 "build/build_config.h" 14 15 namespace base { 16 #if defined(OS_ANDROID) 17 class MessagePumpForUI; 18 #endif 19 20 #if defined(OS_IOS) 21 class MessagePumpUIApplication; 22 #endif 23 24 // Helper class to Run a nested MessageLoop. Please do not use nested 25 // MessageLoops in production code! If you must, use this class instead of 26 // calling MessageLoop::Run/Quit directly. RunLoop::Run can only be called once 27 // per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run 28 // a nested MessageLoop. 29 class BASE_EXPORT RunLoop { 30 public: 31 RunLoop(); 32 ~RunLoop(); 33 34 // Run the current MessageLoop. This blocks until Quit is called. Before 35 // calling Run, be sure to grab the QuitClosure in order to stop the 36 // MessageLoop asynchronously. MessageLoop::QuitWhenIdle and QuitNow will also 37 // trigger a return from Run, but those are deprecated. 38 void Run(); 39 40 // Run the current MessageLoop until it doesn't find any tasks or messages in 41 // the queue (it goes idle). WARNING: This may never return! Only use this 42 // when repeating tasks such as animated web pages have been shut down. 43 void RunUntilIdle(); 44 running()45 bool running() const { return running_; } 46 47 // Quit() quits an earlier call to Run() immediately. QuitWhenIdle() quits an 48 // earlier call to Run() when there aren't any tasks or messages in the queue. 49 // 50 // There can be other nested RunLoops servicing the same task queue 51 // (MessageLoop); Quitting one RunLoop has no bearing on the others. Quit() 52 // and QuitWhenIdle() can be called before, during or after Run(). If called 53 // before Run(), Run() will return immediately when called. Calling Quit() or 54 // QuitWhenIdle() after the RunLoop has already finished running has no 55 // effect. 56 // 57 // WARNING: You must NEVER assume that a call to Quit() or QuitWhenIdle() will 58 // terminate the targetted message loop. If a nested message loop continues 59 // running, the target may NEVER terminate. It is very easy to livelock (run 60 // forever) in such a case. 61 void Quit(); 62 void QuitWhenIdle(); 63 64 // Convenience methods to get a closure that safely calls Quit() or 65 // QuitWhenIdle() (has no effect if the RunLoop instance is gone). 66 // 67 // Example: 68 // RunLoop run_loop; 69 // PostTask(run_loop.QuitClosure()); 70 // run_loop.Run(); 71 base::Closure QuitClosure(); 72 base::Closure QuitWhenIdleClosure(); 73 74 private: 75 friend class MessageLoop; 76 #if defined(OS_ANDROID) 77 // Android doesn't support the blocking MessageLoop::Run, so it calls 78 // BeforeRun and AfterRun directly. 79 friend class base::MessagePumpForUI; 80 #endif 81 82 #if defined(OS_IOS) 83 // iOS doesn't support the blocking MessageLoop::Run, so it calls 84 // BeforeRun directly. 85 friend class base::MessagePumpUIApplication; 86 #endif 87 88 // Return false to abort the Run. 89 bool BeforeRun(); 90 void AfterRun(); 91 92 MessageLoop* loop_; 93 94 // Parent RunLoop or NULL if this is the top-most RunLoop. 95 RunLoop* previous_run_loop_; 96 97 // Used to count how many nested Run() invocations are on the stack. 98 int run_depth_; 99 100 bool run_called_; 101 bool quit_called_; 102 bool running_; 103 104 // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning 105 // that we should quit Run once it becomes idle. 106 bool quit_when_idle_received_; 107 108 // WeakPtrFactory for QuitClosure safety. 109 base::WeakPtrFactory<RunLoop> weak_factory_; 110 111 DISALLOW_COPY_AND_ASSIGN(RunLoop); 112 }; 113 114 } // namespace base 115 116 #endif // BASE_RUN_LOOP_H_ 117