| Index: base/run_loop.h
|
| diff --git a/base/run_loop.h b/base/run_loop.h
|
| index 12976fce5a38acd0adf36d64868f2db2d64d2fb4..c6471273fd2378f6366ef544ef64cbfe4f777c13 100644
|
| --- a/base/run_loop.h
|
| +++ b/base/run_loop.h
|
| @@ -5,11 +5,14 @@
|
| #ifndef BASE_RUN_LOOP_H_
|
| #define BASE_RUN_LOOP_H_
|
|
|
| +#include <stack>
|
| +#include <vector>
|
| +
|
| #include "base/base_export.h"
|
| #include "base/callback.h"
|
| #include "base/macros.h"
|
| #include "base/memory/weak_ptr.h"
|
| -#include "base/message_loop/message_loop.h"
|
| +#include "base/observer_list.h"
|
| #include "base/threading/thread_checker.h"
|
| #include "build/build_config.h"
|
|
|
| @@ -22,25 +25,29 @@ class MessagePumpForUI;
|
| class MessagePumpUIApplication;
|
| #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
|
| +// Helper class to run the RunLoop::Delegate associated with the current thread.
|
| +// A RunLoop::Delegate must have been bound to this thread (ref.
|
| +// RunLoop::RegisterDelegateForCurrentThread()) prior to using any of RunLoop's
|
| +// member and static methods unless explicitly indicated otherwise (e.g.
|
| +// IsRunning/IsNestedOnCurrentThread()). 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.
|
| +// a nested RunLoop but please do not use nested loops in production code!
|
| class BASE_EXPORT RunLoop {
|
| public:
|
| RunLoop();
|
| ~RunLoop();
|
|
|
| - // Run the current MessageLoop. This blocks until Quit is called. Before
|
| + // Run the current RunLoop::Delegate. This blocks until Quit is called. Before
|
| // calling Run, be sure to grab the QuitClosure in order to stop the
|
| - // MessageLoop asynchronously. MessageLoop::QuitWhenIdle and QuitNow will also
|
| - // trigger a return from Run, but those are deprecated.
|
| + // RunLoop::Delegate asynchronously. MessageLoop::QuitWhenIdle and QuitNow
|
| + // will also trigger a return from Run (if RunLoop::Delegate happens to be a
|
| + // MessageLoop...), 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.
|
| + // Run the current RunLoop::Delegate until it doesn't find any tasks or
|
| + // messages in its 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 {
|
| @@ -76,16 +83,13 @@ class BASE_EXPORT RunLoop {
|
| base::Closure QuitClosure();
|
| base::Closure QuitWhenIdleClosure();
|
|
|
| - // Cleans pre-existing TLS state.
|
| - // TODO(gab): Remove this in favor of managing TLS through RunLoop::Delegate
|
| - // as part of the RunLoop<=>MessageLoop split in http://crbug.com/703346.
|
| - static void ResetTLSState();
|
| -
|
| // Returns true if there is an active RunLoop on this thread.
|
| + // Safe to call before RegisterDelegateForCurrentThread().
|
| static bool IsRunningOnCurrentThread();
|
|
|
| // Returns true if there is an active RunLoop on this thread and it's nested
|
| // within another active RunLoop.
|
| + // Safe to call before RegisterDelegateForCurrentThread().
|
| static bool IsNestedOnCurrentThread();
|
|
|
| // A NestingObserver is notified when a nested run loop begins. The observers
|
| @@ -109,7 +113,84 @@ class BASE_EXPORT RunLoop {
|
| // Add/RemoveNestingObserverOnCurrentThread() on this thread will crash.
|
| static void DisallowNestingOnCurrentThread();
|
|
|
| + // A RunLoop::Delegate is a generic interface that allows RunLoop to be
|
| + // separate from the uderlying implementation of the message loop for this
|
| + // thread. It holds private state used by RunLoops on its associated thread.
|
| + // One and only one RunLoop::Delegate must be registered on a given thread
|
| + // via RunLoop::RegisterDelegateForCurrentThread() before RunLoop instances
|
| + // and RunLoop static methods can be used on it.
|
| + class BASE_EXPORT Delegate {
|
| + protected:
|
| + Delegate();
|
| + ~Delegate();
|
| +
|
| + // The client interface provided back to the caller who registers this
|
| + // Delegate via RegisterDelegateForCurrentThread.
|
| + class Client {
|
| + public:
|
| + // Returns the RunLoop with the topmost active Run() call on the stack.
|
| + // TODO(gab): Break the inter-dependency between MessageLoop and RunLoop
|
| + // further. http://crbug.com/703346
|
| + RunLoop* GetTopMostRunLoop() const;
|
| +
|
| + // Returns true if this |outer_| is currently in nested runs. This is a
|
| + // shortcut for RunLoop::IsNestedOnCurrentThread() for the owner of this
|
| + // interface.
|
| + // TODO(gab): consider getting rid of this and the Client class altogether
|
| + // when it's the only method left on Client. http://crbug.com/703346.
|
| + bool IsNested() const;
|
| +
|
| + private:
|
| + // Only a Delegate can instantiate a Delegate::Client.
|
| + friend class Delegate;
|
| + Client(Delegate* outer);
|
| +
|
| + Delegate* outer_;
|
| + };
|
| +
|
| + private:
|
| + // While the state is owned by the Delegate subclass, only RunLoop can use
|
| + // it.
|
| + friend class RunLoop;
|
| +
|
| + // Used by RunLoop to inform its Delegate to Run/Quit. Implementations are
|
| + // expected to keep on running synchronously from the Run() call until the
|
| + // eventual matching Quit() call. Upon receiving a Quit() call it should
|
| + // return from the Run() call as soon as possible without executing
|
| + // remaining tasks/messages. Run() calls can nest in which case each Quit()
|
| + // call should result in the topmost active Run() call returning.
|
| + virtual void Run() = 0;
|
| + virtual void Quit() = 0;
|
| +
|
| + // A vector-based stack is more memory efficient than the default
|
| + // deque-based stack as the active RunLoop stack isn't expected to ever
|
| + // have more than a few entries.
|
| + using RunLoopStack = std::stack<RunLoop*, std::vector<RunLoop*>>;
|
| +
|
| + bool allow_nesting_ = true;
|
| + RunLoopStack active_run_loops_;
|
| + ObserverList<RunLoop::NestingObserver> nesting_observers_;
|
| +
|
| + // True once this Delegate is bound to a thread via
|
| + // RegisterDelegateForCurrentThread().
|
| + bool bound_ = false;
|
| +
|
| + THREAD_CHECKER(bound_thread_checker_);
|
| +
|
| + Client client_interface_ = Client(this);
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Delegate);
|
| + };
|
| +
|
| + // Registers |delegate| on the current thread. Must be called once and only
|
| + // once per thread before using RunLoop methods on it. |delegate| is from then
|
| + // on forever bound to that thread (including its destruction). The returned
|
| + // Delegate::Client is valid as long as |delegate| is kept alive.
|
| + static Delegate::Client* RegisterDelegateForCurrentThread(Delegate* delegate);
|
| +
|
| private:
|
| + // TODO(gab): Break the inter-dependency between MessageLoop and RunLoop
|
| + // further. http://crbug.com/703346
|
| friend class MessageLoop;
|
| #if defined(OS_ANDROID)
|
| // Android doesn't support the blocking MessageLoop::Run, so it calls
|
| @@ -127,7 +208,9 @@ class BASE_EXPORT RunLoop {
|
| bool BeforeRun();
|
| void AfterRun();
|
|
|
| - MessageLoop* loop_;
|
| + // A copy of RunLoop::Delegate for this thread for quick access without using
|
| + // TLS.
|
| + Delegate* delegate_;
|
|
|
| bool run_called_ = false;
|
| bool quit_called_ = false;
|
|
|