| 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
 | 
| 
 |