• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_WIN)
21 class MessagePumpDispatcher;
22 #endif
23 
24 #if defined(OS_IOS)
25 class MessagePumpUIApplication;
26 #endif
27 
28 // Helper class to Run a nested MessageLoop. Please do not use nested
29 // MessageLoops in production code! If you must, use this class instead of
30 // calling MessageLoop::Run/Quit directly. RunLoop::Run can only be called once
31 // per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run
32 // a nested MessageLoop.
33 class BASE_EXPORT RunLoop {
34  public:
35   RunLoop();
36 #if defined(OS_WIN)
37   explicit RunLoop(MessagePumpDispatcher* dispatcher);
38 #endif
39   ~RunLoop();
40 
41   // Run the current MessageLoop. This blocks until Quit is called. Before
42   // calling Run, be sure to grab an AsWeakPtr or the QuitClosure in order to
43   // stop the MessageLoop asynchronously. MessageLoop::QuitWhenIdle and QuitNow
44   // will also trigger a return from Run, but those are deprecated.
45   void Run();
46 
47   // Run the current MessageLoop until it doesn't find any tasks or messages in
48   // the queue (it goes idle). WARNING: This may never return! Only use this
49   // when repeating tasks such as animated web pages have been shut down.
50   void RunUntilIdle();
51 
running()52   bool running() const { return running_; }
53 
54   // Quit an earlier call to Run(). There can be other nested RunLoops servicing
55   // the same task queue (MessageLoop); Quitting one RunLoop has no bearing on
56   // the others. Quit can be called before, during or after Run. If called
57   // before Run, Run will return immediately when called. Calling Quit after the
58   // RunLoop has already finished running has no effect.
59   //
60   // WARNING: You must NEVER assume that a call to Quit will terminate the
61   // targetted message loop. If a nested message loop continues running, the
62   // target may NEVER terminate. It is very easy to livelock (run forever) in
63   // such a case.
64   void Quit();
65 
66   // Convenience method to get a closure that safely calls Quit (has no effect
67   // if the RunLoop instance is gone).
68   //
69   // Example:
70   //   RunLoop run_loop;
71   //   PostTask(run_loop.QuitClosure());
72   //   run_loop.Run();
73   base::Closure QuitClosure();
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 #if defined(OS_WIN)
99   MessagePumpDispatcher* dispatcher_;
100 #endif
101 
102   // Used to count how many nested Run() invocations are on the stack.
103   int run_depth_;
104 
105   bool run_called_;
106   bool quit_called_;
107   bool running_;
108 
109   // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning
110   // that we should quit Run once it becomes idle.
111   bool quit_when_idle_received_;
112 
113   // WeakPtrFactory for QuitClosure safety.
114   base::WeakPtrFactory<RunLoop> weak_factory_;
115 
116   DISALLOW_COPY_AND_ASSIGN(RunLoop);
117 };
118 
119 }  // namespace base
120 
121 #endif  // BASE_RUN_LOOP_H_
122