Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: base/run_loop.h

Issue 2818533003: Make nesting/running states a RunLoop rather than a MessageLoop concept. (Closed)
Patch Set: fix compile and add RunLoopTests Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_RUN_LOOP_H_ 5 #ifndef BASE_RUN_LOOP_H_
6 #define BASE_RUN_LOOP_H_ 6 #define BASE_RUN_LOOP_H_
7 7
8 #include "base/base_export.h" 8 #include "base/base_export.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/macros.h" 10 #include "base/macros.h"
(...skipping 11 matching lines...) Expand all
22 class MessagePumpUIApplication; 22 class MessagePumpUIApplication;
23 #endif 23 #endif
24 24
25 // Helper class to Run a nested MessageLoop. Please do not use nested 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 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 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 28 // per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run
29 // a nested MessageLoop. 29 // a nested MessageLoop.
30 class BASE_EXPORT RunLoop { 30 class BASE_EXPORT RunLoop {
31 public: 31 public:
32 class Delegate {};
33
32 RunLoop(); 34 RunLoop();
33 ~RunLoop(); 35 ~RunLoop();
34 36
35 // Run the current MessageLoop. This blocks until Quit is called. Before 37 // 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 38 // calling Run, be sure to grab the QuitClosure in order to stop the
37 // MessageLoop asynchronously. MessageLoop::QuitWhenIdle and QuitNow will also 39 // MessageLoop asynchronously. MessageLoop::QuitWhenIdle and QuitNow will also
38 // trigger a return from Run, but those are deprecated. 40 // trigger a return from Run, but those are deprecated.
39 void Run(); 41 void Run();
40 42
41 // Run the current MessageLoop until it doesn't find any tasks or messages in 43 // 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 44 // 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. 45 // when repeating tasks such as animated web pages have been shut down.
44 void RunUntilIdle(); 46 void RunUntilIdle();
45 47
46 bool running() const { return running_; } 48 bool running() const {
49 DCHECK(thread_checker_.CalledOnValidThread());
50 return running_;
51 }
47 52
48 // Quit() quits an earlier call to Run() immediately. QuitWhenIdle() quits an 53 // 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. 54 // earlier call to Run() when there aren't any tasks or messages in the queue.
50 // 55 //
51 // There can be other nested RunLoops servicing the same task queue 56 // There can be other nested RunLoops servicing the same task queue
52 // (MessageLoop); Quitting one RunLoop has no bearing on the others. Quit() 57 // (MessageLoop); Quitting one RunLoop has no bearing on the others. Quit()
53 // and QuitWhenIdle() can be called before, during or after Run(). If called 58 // and QuitWhenIdle() can be called before, during or after Run(). If called
54 // before Run(), Run() will return immediately when called. Calling Quit() or 59 // before Run(), Run() will return immediately when called. Calling Quit() or
55 // QuitWhenIdle() after the RunLoop has already finished running has no 60 // QuitWhenIdle() after the RunLoop has already finished running has no
56 // effect. 61 // effect.
57 // 62 //
58 // WARNING: You must NEVER assume that a call to Quit() or QuitWhenIdle() will 63 // 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 64 // 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 65 // running, the target may NEVER terminate. It is very easy to livelock (run
61 // forever) in such a case. 66 // forever) in such a case.
62 void Quit(); 67 void Quit();
63 void QuitWhenIdle(); 68 void QuitWhenIdle();
64 69
65 // Convenience methods to get a closure that safely calls Quit() or 70 // Convenience methods to get a closure that safely calls Quit() or
66 // QuitWhenIdle() (has no effect if the RunLoop instance is gone). 71 // QuitWhenIdle() (has no effect if the RunLoop instance is gone).
67 // 72 //
68 // Example: 73 // Example:
69 // RunLoop run_loop; 74 // RunLoop run_loop;
70 // PostTask(run_loop.QuitClosure()); 75 // PostTask(run_loop.QuitClosure());
71 // run_loop.Run(); 76 // run_loop.Run();
72 base::Closure QuitClosure(); 77 base::Closure QuitClosure();
73 base::Closure QuitWhenIdleClosure(); 78 base::Closure QuitWhenIdleClosure();
74 79
80 // Returns true if there is an active RunLoop on this thread.
81 static bool IsRunningOnCurrentThread();
82
83 // Returns true if there is an active RunLoop on this thread and it's nested
84 // within another active RunLoop.
85 static bool IsNestedOnCurrentThread();
86
87 // A NestingObserver is notified when a nested run loop begins. The observers
88 // are notified before the current thread's RunLoop::Delegate::Run() is
89 // invoked and nested work begins.
90 class BASE_EXPORT NestingObserver {
91 public:
92 virtual void OnBeginNestedMessageLoop() = 0;
93
94 protected:
95 virtual ~NestingObserver() = default;
96 };
97
98 static void AddNestingObserverOnCurrentThread(NestingObserver* observer);
99 static void RemoveNestingObserverOnCurrentThread(NestingObserver* observer);
100
101 // Returns true if nesting is allowed on this thread.
102 static bool IsNestingAllowedOnCurrentThread();
103
104 // Disallow nesting. After this is called, running a nested RunLoop or calling
105 // Add/RemoveNestingObserverOnCurrentThread() on this thread will crash.
106 static void DisallowNestingOnCurrentThread();
107
75 private: 108 private:
76 friend class MessageLoop; 109 friend class MessageLoop;
77 #if defined(OS_ANDROID) 110 #if defined(OS_ANDROID)
78 // Android doesn't support the blocking MessageLoop::Run, so it calls 111 // Android doesn't support the blocking MessageLoop::Run, so it calls
79 // BeforeRun and AfterRun directly. 112 // BeforeRun and AfterRun directly.
80 friend class base::MessagePumpForUI; 113 friend class base::MessagePumpForUI;
81 #endif 114 #endif
82 115
83 #if defined(OS_IOS) 116 #if defined(OS_IOS)
84 // iOS doesn't support the blocking MessageLoop::Run, so it calls 117 // iOS doesn't support the blocking MessageLoop::Run, so it calls
85 // BeforeRun directly. 118 // BeforeRun directly.
86 friend class base::MessagePumpUIApplication; 119 friend class base::MessagePumpUIApplication;
87 #endif 120 #endif
88 121
89 // Return false to abort the Run. 122 // Return false to abort the Run.
90 bool BeforeRun(); 123 bool BeforeRun();
91 void AfterRun(); 124 void AfterRun();
92 125
93 MessageLoop* loop_; 126 MessageLoop* loop_;
94 127
95 // Parent RunLoop or NULL if this is the top-most RunLoop. 128 bool run_called_ = false;
96 RunLoop* previous_run_loop_; 129 bool quit_called_ = false;
97 130 bool running_ = false;
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 131
105 // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning 132 // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning
106 // that we should quit Run once it becomes idle. 133 // that we should quit Run once it becomes idle.
107 bool quit_when_idle_received_; 134 bool quit_when_idle_received_ = false;
108 135
136 // RunLoop's non-static methods are affine to thread it's running on.
109 base::ThreadChecker thread_checker_; 137 base::ThreadChecker thread_checker_;
110 138
111 // WeakPtrFactory for QuitClosure safety. 139 // WeakPtrFactory for QuitClosure safety.
112 base::WeakPtrFactory<RunLoop> weak_factory_; 140 base::WeakPtrFactory<RunLoop> weak_factory_;
113 141
114 DISALLOW_COPY_AND_ASSIGN(RunLoop); 142 DISALLOW_COPY_AND_ASSIGN(RunLoop);
115 }; 143 };
116 144
117 } // namespace base 145 } // namespace base
118 146
119 #endif // BASE_RUN_LOOP_H_ 147 #endif // BASE_RUN_LOOP_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698