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

Unified Diff: base/message_loop.h

Issue 10479018: Add base::RunLoop and update ui_test_utils to use it to reduce flakiness (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: jar, phajdan feedback Created 8 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/message_loop.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/message_loop.h
diff --git a/base/message_loop.h b/base/message_loop.h
index d78b58addc2019ad46b61e79adf8c918f432a9dd..c9baa4f70e9f0810053eeb2e0d60bc5bde71b4e1 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -217,30 +217,111 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
this, from_here, object);
}
+ protected:
+ class RunState;
+
+ // RunIDObject is used by Run and QuitNowWithID to quit a particular nested
+ // call to MessageLoop::Run. Call GetRunID to get a RunIDObject for use with
+ // one pair of Run/Quit calls. You can not reuse a RunIDObject.
+ class RunIDObject : public base::RefCounted<RunIDObject> {
+ private:
+ friend class base::RefCounted<RunIDObject>;
+ friend class MessageLoop;
+
+ RunIDObject() : run_state_(NULL), used_(false), quit_now_received_(false) {}
+ ~RunIDObject() {}
+
+ RunState* run_state_;
+ bool used_;
+
+ // Used to record that QuitNowWithID() was called at this run_depth_.
+ bool quit_now_received_;
+
+ DISALLOW_COPY_AND_ASSIGN(RunIDObject);
+ };
+
+ public:
+
+ typedef scoped_refptr<RunIDObject> RunID;
+
// Run the message loop.
void Run();
+ // Run the message loop with the given |run_id|. |run_id| must be retrieved by
+ // an earlier call to GetRunID.
+ void RunWithID(const RunID& run_id);
darin (slow to review) 2012/06/19 17:55:51 [Sorry, detour incoming!!] I think it would be he
jbates 2012/06/22 02:12:51 RunLoop done with some slight semantic changes. I
+
// Process all pending tasks, windows messages, etc., but don't wait/sleep.
// Return as soon as all items that can be run are taken care of.
void RunAllPending();
- // Signals the Run method to return after it is done processing all pending
- // messages. This method may only be called on the same thread that called
- // Run, and Run must still be on the call stack.
+ // TODO(jbates) remove this. crbug.com/131220. See QuitWhenIdle().
+ void Quit() { QuitWhenIdle(); }
+
+ // Signals the Run method to return when it becomes idle. It will continue to
+ // process pending messages and future messages as long as they are enqueued.
+ // Warning: if the MessageLoop remains busy, it may never quit. Only use this
+ // Quit method when looping procedures (such as web pages) have been shut
+ // down.
//
- // Use QuitClosure if you need to Quit another thread's MessageLoop, but note
- // that doing so is fairly dangerous if the target thread makes nested calls
- // to MessageLoop::Run. The problem being that you won't know which nested
- // run loop you are quitting, so be careful!
- void Quit();
+ // This method may only be called on the same thread that called Run, and Run
+ // must still be on the call stack.
+ //
+ // Use Quit*Closure variants if you need to Quit another thread's MessageLoop,
+ // but note that doing so is fairly dangerous if the target thread makes
+ // nested calls to MessageLoop::Run. The problem being that you won't know
+ // which nested run loop you are quitting, so be careful!
+ void QuitWhenIdle();
// This method is a variant of Quit, that does not wait for pending messages
// to be processed before returning from Run.
void QuitNow();
- // Invokes Quit on the current MessageLoop when run. Useful to schedule an
- // arbitrary MessageLoop to Quit.
- static base::Closure QuitClosure();
+ // This method is a variant of QuitNow that applies to a specific nested call
+ // to MessageLoop::Run(). Although nesting is strongly discouraged, it can be
+ // handy for tests. Use QuitNowWithID to make nesting and quit behavior more
+ // predictable. |run_id| is returned by an earlier call to
+ // GetRunID(). QuitWithID has the following behavior:
+ // - If the corresponding MessageLoop::RunWithID call has already completed,
+ // nothing happens.
+ // - If the corresponding MessageLoop::RunWithID has not been called yet, it
+ // will become a no-op when it is eventually called.
+ // - If there are one or more nested calls to MessageLoop::Run inside the
+ // target RunWithID call, the QuitNow is deferred until all nested Run calls
+ // have completed.
+ // WARNING: You must NEVER assume that a call to QuitNowWithID will terminate
+ // the targetted message loop. If a nested message loop continues running, the
+ // target may NEVER terminate. It is very easy to livelock (run forever) in
+ // such a case.
+ void QuitNowWithID(const RunID& run_id);
+
+ // TODO(jbates) remove this. crbug.com/131220. See QuitWhenIdleClosure().
+ static base::Closure QuitClosure() { return QuitWhenIdleClosure(); }
+
+ // Construct a Closure that will call QuitWhenIdle(). Useful to schedule an
+ // arbitrary MessageLoop to QuitWhenIdle.
+ static base::Closure QuitWhenIdleClosure();
+
+ // Construct a Closure that will call QuitNow(). Useful to schedule an
+ // arbitrary MessageLoop to QuitNow.
+ static base::Closure QuitNowClosure();
+
+ // Construct a Closure that will call QuitNowWithID(run_id). Useful to
+ // schedule an arbitrary MessageLoop to QuitNowWithID.
+ static base::Closure QuitNowWithIDClosure(const RunID& run_id);
+
+ // Get a run id for use with MessageLoop::Run and MessageLoop::QuitNowWithID.
+ // Use this value to quit a specific nested call to MessageLoop::Run. The
+ // value returned by GetRunID is only for use on the same MessageLoop
+ // instance. For example:
+ //
+ // // Record GetRunID before running the MessageLoop:
+ // run_id_ = MessageLoop::current()->GetRunID();
+ // MessageLoop::current()->RunWithID(run_id_);
+ //
+ // // Then, during a task or callback during the above call to Run:
+ // MessageLoop::current()->QuitNowWithID(run_id_);
+ RunID GetRunID();
// Returns the type passed to the constructor.
Type type() const { return type_; }
@@ -362,17 +443,25 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
//----------------------------------------------------------------------------
protected:
- struct RunState {
+ class BASE_EXPORT RunState {
+ public:
+ RunState();
+
+ // Used to distinguish this RunState from other nested RunStates.
+ RunID run_state_id_;
+
// Used to count how many Run() invocations are on the stack.
- int run_depth;
+ int run_depth_;
// Used to record that Quit() was called, or that we should quit the pump
// once it becomes idle.
- bool quit_received;
+ bool quit_received_;
#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
- Dispatcher* dispatcher;
+ Dispatcher* dispatcher_;
#endif
+ protected:
+ ~RunState();
};
#if defined(OS_ANDROID)
@@ -382,7 +471,7 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
#endif
class BASE_EXPORT AutoRunState : RunState {
public:
- explicit AutoRunState(MessageLoop* loop);
+ AutoRunState(MessageLoop* loop, const RunID& run_id);
~AutoRunState();
private:
MessageLoop* loop_;
@@ -572,6 +661,7 @@ class BASE_EXPORT MessageLoopForUI : public MessageLoop {
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
void RunWithDispatcher(Dispatcher* dispatcher);
+ void RunWithDispatcher(Dispatcher* dispatcher, const RunID& run_id);
void RunAllPendingWithDispatcher(Dispatcher* dispatcher);
protected:
« no previous file with comments | « no previous file | base/message_loop.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698