michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_RUN_LOOP_H_ michael@0: #define BASE_RUN_LOOP_H_ michael@0: michael@0: #include "base/base_export.h" michael@0: #include "base/callback.h" michael@0: #include "base/memory/weak_ptr.h" michael@0: #include "base/message_loop/message_loop.h" michael@0: michael@0: namespace base { michael@0: #if defined(OS_ANDROID) michael@0: class MessagePumpForUI; michael@0: #endif michael@0: michael@0: #if defined(OS_IOS) michael@0: class MessagePumpUIApplication; michael@0: #endif michael@0: michael@0: // Helper class to Run a nested MessageLoop. Please do not use nested michael@0: // MessageLoops in production code! If you must, use this class instead of michael@0: // calling MessageLoop::Run/Quit directly. RunLoop::Run can only be called once michael@0: // per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run michael@0: // a nested MessageLoop. michael@0: class BASE_EXPORT RunLoop { michael@0: public: michael@0: RunLoop(); michael@0: #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \ michael@0: !defined(USE_GTK_MESSAGE_PUMP) michael@0: explicit RunLoop(MessageLoop::Dispatcher* dispatcher); michael@0: #endif michael@0: ~RunLoop(); michael@0: michael@0: #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \ michael@0: !defined(USE_GTK_MESSAGE_PUMP) michael@0: void set_dispatcher(MessageLoop::Dispatcher* dispatcher) { michael@0: dispatcher_ = dispatcher; michael@0: } michael@0: #endif michael@0: michael@0: // Run the current MessageLoop. This blocks until Quit is called. Before michael@0: // calling Run, be sure to grab an AsWeakPtr or the QuitClosure in order to michael@0: // stop the MessageLoop asynchronously. MessageLoop::Quit and QuitNow will michael@0: // also trigger a return from Run, but those are deprecated. michael@0: void Run(); michael@0: michael@0: // Run the current MessageLoop until it doesn't find any tasks or messages in michael@0: // the queue (it goes idle). WARNING: This may never return! Only use this michael@0: // when repeating tasks such as animated web pages have been shut down. michael@0: void RunUntilIdle(); michael@0: michael@0: bool running() const { return running_; } michael@0: michael@0: // Quit an earlier call to Run(). There can be other nested RunLoops servicing michael@0: // the same task queue (MessageLoop); Quitting one RunLoop has no bearing on michael@0: // the others. Quit can be called before, during or after Run. If called michael@0: // before Run, Run will return immediately when called. Calling Quit after the michael@0: // RunLoop has already finished running has no effect. michael@0: // michael@0: // WARNING: You must NEVER assume that a call to Quit will terminate the michael@0: // targetted message loop. If a nested message loop continues running, the michael@0: // target may NEVER terminate. It is very easy to livelock (run forever) in michael@0: // such a case. michael@0: void Quit(); michael@0: michael@0: // Convenience method to get a closure that safely calls Quit (has no effect michael@0: // if the RunLoop instance is gone). michael@0: // michael@0: // Example: michael@0: // RunLoop run_loop; michael@0: // PostTask(run_loop.QuitClosure()); michael@0: // run_loop.Run(); michael@0: base::Closure QuitClosure(); michael@0: michael@0: private: michael@0: friend class MessageLoop; michael@0: #if defined(OS_ANDROID) michael@0: // Android doesn't support the blocking MessageLoop::Run, so it calls michael@0: // BeforeRun and AfterRun directly. michael@0: friend class base::MessagePumpForUI; michael@0: #endif michael@0: michael@0: #if defined(OS_IOS) michael@0: // iOS doesn't support the blocking MessageLoop::Run, so it calls michael@0: // BeforeRun directly. michael@0: friend class base::MessagePumpUIApplication; michael@0: #endif michael@0: michael@0: // Return false to abort the Run. michael@0: bool BeforeRun(); michael@0: void AfterRun(); michael@0: michael@0: MessageLoop* loop_; michael@0: michael@0: // WeakPtrFactory for QuitClosure safety. michael@0: base::WeakPtrFactory weak_factory_; michael@0: michael@0: // Parent RunLoop or NULL if this is the top-most RunLoop. michael@0: RunLoop* previous_run_loop_; michael@0: michael@0: #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \ michael@0: !defined(USE_GTK_MESSAGE_PUMP) michael@0: MessageLoop::Dispatcher* dispatcher_; michael@0: #endif michael@0: michael@0: // Used to count how many nested Run() invocations are on the stack. michael@0: int run_depth_; michael@0: michael@0: bool run_called_; michael@0: bool quit_called_; michael@0: bool running_; michael@0: michael@0: // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning michael@0: // that we should quit Run once it becomes idle. michael@0: bool quit_when_idle_received_; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(RunLoop); michael@0: }; michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // BASE_RUN_LOOP_H_