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

Unified Diff: base/run_loop.cc

Issue 2880453003: Introduce RunLoop::Delegate splitting RunLoop/MessageLoop some more. (Closed)
Patch Set: oops, re-invert IsRunning logic Created 3 years, 7 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 | « base/run_loop.h ('k') | components/download/internal/scheduler/network_listener_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/run_loop.cc
diff --git a/base/run_loop.cc b/base/run_loop.cc
index b7df5b23d8d72f737c5c6f468c508ec12ade8fd9..b87688d547b348b6fd2fc4aa8583153b7a123aa8 100644
--- a/base/run_loop.cc
+++ b/base/run_loop.cc
@@ -4,12 +4,9 @@
#include "base/run_loop.h"
-#include <stack>
-
#include "base/bind.h"
#include "base/lazy_instance.h"
-#include "base/observer_list.h"
-#include "base/threading/thread_local_storage.h"
+#include "base/threading/thread_local.h"
#include "base/tracked_objects.h"
#include "build/build_config.h"
@@ -17,74 +14,58 @@ namespace base {
namespace {
-class ThreadLocalRunLoopState {
- public:
- // 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*>>;
-
- ThreadLocalRunLoopState()
- : slot_(&ThreadLocalRunLoopState::OnTLSDestruction) {}
-
- ~ThreadLocalRunLoopState() = delete;
-
- RunLoopStack& GetActiveRunLoops() {
- return GetOrCreateInternalState()->active_run_loops;
- }
-
- ObserverList<RunLoop::NestingObserver>& GetNestingObservers() {
- InternalState* state = GetOrCreateInternalState();
- CHECK(state->allow_nesting);
- return state->nesting_observers;
- }
-
- bool IsNestingAllowed() { return GetOrCreateInternalState()->allow_nesting; }
+LazyInstance<ThreadLocalPointer<RunLoop::Delegate>>::Leaky tls_delegate =
+ LAZY_INSTANCE_INITIALIZER;
- void DisallowNesting() { GetOrCreateInternalState()->allow_nesting = false; }
+} // namespace
- void Reset() {
- InternalState* state = static_cast<InternalState*>(slot_.Get());
- if (state) {
- slot_.Set(nullptr);
- delete state;
- }
- }
+RunLoop::Delegate::Delegate() {
+ // The Delegate can be created on another thread. It is only bound in
+ // RegisterDelegateForCurrentThread().
+ DETACH_FROM_THREAD(bound_thread_checker_);
+}
- private:
- struct InternalState {
- bool allow_nesting = true;
- RunLoopStack active_run_loops;
- ObserverList<RunLoop::NestingObserver> nesting_observers;
- };
+RunLoop::Delegate::~Delegate() {
+ DCHECK_CALLED_ON_VALID_THREAD(bound_thread_checker_);
+ // A RunLoop::Delegate may be destroyed before it is bound, if so it may still
+ // be on its creation thread (e.g. a Thread that fails to start) and
+ // shouldn't disrupt that thread's state.
+ if (bound_)
+ tls_delegate.Get().Set(nullptr);
+}
- static void OnTLSDestruction(void* internal_state) {
- delete static_cast<InternalState*>(internal_state);
- }
+RunLoop* RunLoop::Delegate::Client::GetTopMostRunLoop() const {
+ DCHECK_CALLED_ON_VALID_THREAD(outer_->bound_thread_checker_);
+ DCHECK(outer_->bound_);
+ return outer_->active_run_loops_.empty() ? nullptr
+ : outer_->active_run_loops_.top();
+}
- InternalState* GetOrCreateInternalState() {
- InternalState* state = static_cast<InternalState*>(slot_.Get());
- if (!state) {
- state = new InternalState;
- slot_.Set(static_cast<void*>(state));
- }
- return state;
- }
+bool RunLoop::Delegate::Client::IsNested() const {
+ DCHECK_CALLED_ON_VALID_THREAD(outer_->bound_thread_checker_);
+ DCHECK(outer_->bound_);
+ return outer_->active_run_loops_.size() > 1;
+}
- ThreadLocalStorage::Slot slot_;
+RunLoop::Delegate::Client::Client(Delegate* outer) : outer_(outer) {}
- DISALLOW_COPY_AND_ASSIGN(ThreadLocalRunLoopState);
-};
+RunLoop::Delegate::Client* RunLoop::RegisterDelegateForCurrentThread(
+ Delegate* delegate) {
+ // Bind |delegate| to this thread.
+ DCHECK(!delegate->bound_);
+ DCHECK_CALLED_ON_VALID_THREAD(delegate->bound_thread_checker_);
-LazyInstance<ThreadLocalRunLoopState>::Leaky tls_run_loop_state =
- LAZY_INSTANCE_INITIALIZER;
+ // There can only be one RunLoop::Delegate per thread.
+ DCHECK(!tls_delegate.Get().Get());
+ tls_delegate.Get().Set(delegate);
+ delegate->bound_ = true;
-} // namespace
+ return &delegate->client_interface_;
+}
-RunLoop::RunLoop()
- : loop_(MessageLoop::current()),
- weak_factory_(this) {
- DCHECK(loop_);
+RunLoop::RunLoop() : delegate_(tls_delegate.Get().Get()), weak_factory_(this) {
+ // A RunLoop::Delegate must be bound to this thread prior to using RunLoop.
+ DCHECK(delegate_);
}
RunLoop::~RunLoop() {
@@ -102,7 +83,7 @@ void RunLoop::Run() {
// any.
tracked_objects::TaskStopwatch stopwatch;
stopwatch.Start();
- loop_->RunHandler();
+ delegate_->Run();
stopwatch.Stop();
AfterRun();
@@ -119,9 +100,9 @@ void RunLoop::Quit() {
DCHECK(thread_checker_.CalledOnValidThread());
quit_called_ = true;
- if (running_ && loop_->run_loop_ == this) {
+ if (running_ && delegate_->active_run_loops_.top() == this) {
// This is the inner-most RunLoop, so quit now.
- loop_->QuitNow();
+ delegate_->Quit();
}
}
@@ -143,38 +124,41 @@ base::Closure RunLoop::QuitWhenIdleClosure() {
}
// static
-void RunLoop::ResetTLSState() {
- tls_run_loop_state.Get().Reset();
-}
-
-// static
bool RunLoop::IsRunningOnCurrentThread() {
- return !tls_run_loop_state.Get().GetActiveRunLoops().empty();
+ Delegate* delegate = tls_delegate.Get().Get();
+ return delegate && !delegate->active_run_loops_.empty();
}
// static
bool RunLoop::IsNestedOnCurrentThread() {
- return tls_run_loop_state.Get().GetActiveRunLoops().size() > 1;
+ Delegate* delegate = tls_delegate.Get().Get();
+ return delegate && delegate->active_run_loops_.size() > 1;
}
// static
void RunLoop::AddNestingObserverOnCurrentThread(NestingObserver* observer) {
- tls_run_loop_state.Get().GetNestingObservers().AddObserver(observer);
+ Delegate* delegate = tls_delegate.Get().Get();
+ DCHECK(delegate);
+ CHECK(delegate->allow_nesting_);
+ delegate->nesting_observers_.AddObserver(observer);
}
// static
void RunLoop::RemoveNestingObserverOnCurrentThread(NestingObserver* observer) {
- tls_run_loop_state.Get().GetNestingObservers().RemoveObserver(observer);
+ Delegate* delegate = tls_delegate.Get().Get();
+ DCHECK(delegate);
+ CHECK(delegate->allow_nesting_);
+ delegate->nesting_observers_.RemoveObserver(observer);
}
// static
bool RunLoop::IsNestingAllowedOnCurrentThread() {
- return tls_run_loop_state.Get().IsNestingAllowed();
+ return tls_delegate.Get().Get()->allow_nesting_;
}
// static
void RunLoop::DisallowNestingOnCurrentThread() {
- tls_run_loop_state.Get().DisallowNesting();
+ tls_delegate.Get().Get()->allow_nesting_ = false;
}
bool RunLoop::BeforeRun() {
@@ -187,19 +171,14 @@ bool RunLoop::BeforeRun() {
if (quit_called_)
return false;
- auto& active_run_loops = tls_run_loop_state.Get().GetActiveRunLoops();
- active_run_loops.push(this);
-
- const bool is_nested = active_run_loops.size() > 1;
+ auto& active_run_loops_ = delegate_->active_run_loops_;
+ active_run_loops_.push(this);
- // TODO(gab): Break the inter-dependency between MessageLoop and RunLoop
- // further. http://crbug.com/703346
- loop_->run_loop_ = this;
- loop_->is_nested_ = is_nested;
+ const bool is_nested = active_run_loops_.size() > 1;
if (is_nested) {
- CHECK(tls_run_loop_state.Get().IsNestingAllowed());
- for (auto& observer : tls_run_loop_state.Get().GetNestingObservers())
+ CHECK(delegate_->allow_nesting_);
+ for (auto& observer : delegate_->nesting_observers_)
observer.OnBeginNestedRunLoop();
}
@@ -212,18 +191,16 @@ void RunLoop::AfterRun() {
running_ = false;
- auto& active_run_loops = tls_run_loop_state.Get().GetActiveRunLoops();
- DCHECK_EQ(active_run_loops.top(), this);
- active_run_loops.pop();
+ auto& active_run_loops_ = delegate_->active_run_loops_;
+ DCHECK_EQ(active_run_loops_.top(), this);
+ active_run_loops_.pop();
RunLoop* previous_run_loop =
- active_run_loops.empty() ? nullptr : active_run_loops.top();
- loop_->run_loop_ = previous_run_loop;
- loop_->is_nested_ = active_run_loops.size() > 1;
+ active_run_loops_.empty() ? nullptr : active_run_loops_.top();
// Execute deferred QuitNow, if any:
if (previous_run_loop && previous_run_loop->quit_called_)
- loop_->QuitNow();
+ delegate_->Quit();
}
} // namespace base
« no previous file with comments | « base/run_loop.h ('k') | components/download/internal/scheduler/network_listener_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698