summaryrefslogtreecommitdiffstats
path: root/base/run_loop.h
diff options
context:
space:
mode:
authorjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-28 22:57:30 +0000
committerjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-28 22:57:30 +0000
commit8e937c1e6a1cf0bdce081324965e105a6b17a3fc (patch)
treeffec2c670d3ceb188c0c1244b846b15adbe7838e /base/run_loop.h
parented50d3ee0ed2e26da0ff805dc52ee0c03f80df2e (diff)
downloadchromium_src-8e937c1e6a1cf0bdce081324965e105a6b17a3fc.zip
chromium_src-8e937c1e6a1cf0bdce081324965e105a6b17a3fc.tar.gz
chromium_src-8e937c1e6a1cf0bdce081324965e105a6b17a3fc.tar.bz2
Add base::RunLoop and update ui_test_utils to use it to reduce flakiness
Timeout flakiness has been observed in multiple tests that use Quit. This changes various test utility APIs to use QuitNow via base::RunLoop instead. Some instances of Quit are left as-is where it appears they may have a use case. The ui_test_utils QuitThisRunLoop function does a safer form of MessageLoop::QuitWhenIdle that allows a few generations of tasks to run before actually quitting the MessageLoop. This addresses the design assumptions of many existing tests while hopefully reducing flaky timeouts by moving away from QuitWhenIdle. This fixes throughput_tests.cc which is currently timing out on Mac. BUG=124906,130141,131220,128305,132932 Review URL: https://chromiumcodereview.appspot.com/10479018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144824 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/run_loop.h')
-rw-r--r--base/run_loop.h112
1 files changed, 112 insertions, 0 deletions
diff --git a/base/run_loop.h b/base/run_loop.h
new file mode 100644
index 0000000..6fc0ed2
--- /dev/null
+++ b/base/run_loop.h
@@ -0,0 +1,112 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_RUN_LOOP_H_
+#define BASE_RUN_LOOP_H_
+#pragma once
+
+#include "base/base_export.h"
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop.h"
+
+namespace base {
+#if defined(OS_ANDROID)
+class MessagePumpForUI;
+#endif
+
+// Helper class to Run a nested MessageLoop. Please do not use nested
+// MessageLoops in production code! If you must, use this class instead of
+// calling MessageLoop::Run/Quit directly. RunLoop::Run can only be called once
+// per RunLoop lifetime. Create a RunLoop on the stack and call Run/Quit to run
+// a nested MessageLoop.
+class BASE_EXPORT RunLoop {
+ public:
+ RunLoop();
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ explicit RunLoop(MessageLoop::Dispatcher* dispatcher);
+#endif
+ ~RunLoop();
+
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ void set_dispatcher(MessageLoop::Dispatcher* dispatcher) {
+ dispatcher_ = dispatcher;
+ }
+#endif
+
+ // Run the current MessageLoop. This blocks until Quit is called. Before
+ // calling Run, be sure to grab an AsWeakPtr or the QuitClosure in order to
+ // stop the MessageLoop asynchronously. MessageLoop::Quit and QuitNow will
+ // also trigger a return from Run, but those are deprecated.
+ void Run();
+
+ // Run the current MessageLoop until it doesn't find any tasks or messages in
+ // the queue (it goes idle). WARNING: This may never return! Only use this
+ // when repeating tasks such as animated web pages have been shut down.
+ void RunUntilIdle();
+
+ bool running() const { return running_; }
+
+ // Quit an earlier call to Run(). There can be other nested RunLoops servicing
+ // the same task queue (MessageLoop); Quitting one RunLoop has no bearing on
+ // the others. Quit can be called before, during or after Run. If called
+ // before Run, Run will return immediately when called. Calling Quit after the
+ // RunLoop has already finished running has no effect.
+ //
+ // WARNING: You must NEVER assume that a call to Quit 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 Quit();
+
+ // Convenience method to get a closure that safely calls Quit (has no effect
+ // if the RunLoop instance is gone).
+ //
+ // Example:
+ // RunLoop run_loop;
+ // PostTask(run_loop.QuitClosure());
+ // run_loop.Run();
+ base::Closure QuitClosure();
+
+ private:
+ friend class ::MessageLoop;
+#if defined(OS_ANDROID)
+ // Android doesn't support the blocking MessageLoop::Run, so it calls
+ // BeforeRun and AfterRun directly.
+ friend class base::MessagePumpForUI;
+#endif
+
+ // Return false to abort the Run.
+ bool BeforeRun();
+ void AfterRun();
+
+ MessageLoop* loop_;
+
+ // WeakPtrFactory for QuitClosure safety.
+ base::WeakPtrFactory<RunLoop> weak_factory_;
+
+ // Parent RunLoop or NULL if this is the top-most RunLoop.
+ RunLoop* previous_run_loop_;
+
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ MessageLoop::Dispatcher* dispatcher_;
+#endif
+
+ // Used to count how many nested Run() invocations are on the stack.
+ int run_depth_;
+
+ bool run_called_;
+ bool quit_called_;
+ bool running_;
+
+ // Used to record that QuitWhenIdle() was called on the MessageLoop, meaning
+ // that we should quit Run once it becomes idle.
+ bool quit_when_idle_received_;
+
+ DISALLOW_COPY_AND_ASSIGN(RunLoop);
+};
+
+} // namespace base
+
+#endif // BASE_RUN_LOOP_H_