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
15namespace base {
16#if defined(OS_ANDROID)
17class MessagePumpForUI;
18#endif
19
20#if defined(OS_WIN)
21class MessagePumpDispatcher;
22#endif
23
24#if defined(OS_IOS)
25class 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.
33class 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
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