|  | // 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. | 
|  |  | 
|  | #include "base/run_loop.h" | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/tracked_objects.h" | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | #include "base/message_loop/message_pump_dispatcher.h" | 
|  | #endif | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | RunLoop::RunLoop() | 
|  | : loop_(MessageLoop::current()), | 
|  | previous_run_loop_(NULL), | 
|  | run_depth_(0), | 
|  | run_called_(false), | 
|  | quit_called_(false), | 
|  | running_(false), | 
|  | quit_when_idle_received_(false), | 
|  | weak_factory_(this) { | 
|  | #if defined(OS_WIN) | 
|  | dispatcher_ = NULL; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | RunLoop::RunLoop(MessagePumpDispatcher* dispatcher) | 
|  | : loop_(MessageLoop::current()), | 
|  | previous_run_loop_(NULL), | 
|  | dispatcher_(dispatcher), | 
|  | run_depth_(0), | 
|  | run_called_(false), | 
|  | quit_called_(false), | 
|  | running_(false), | 
|  | quit_when_idle_received_(false), | 
|  | weak_factory_(this) { | 
|  | } | 
|  | #endif | 
|  |  | 
|  | RunLoop::~RunLoop() { | 
|  | } | 
|  |  | 
|  | void RunLoop::Run() { | 
|  | if (!BeforeRun()) | 
|  | return; | 
|  |  | 
|  | // Use task stopwatch to exclude the loop run time from the current task, if | 
|  | // any. | 
|  | tracked_objects::TaskStopwatch stopwatch; | 
|  | stopwatch.Start(); | 
|  | loop_->RunHandler(); | 
|  | stopwatch.Stop(); | 
|  |  | 
|  | AfterRun(); | 
|  | } | 
|  |  | 
|  | void RunLoop::RunUntilIdle() { | 
|  | quit_when_idle_received_ = true; | 
|  | Run(); | 
|  | } | 
|  |  | 
|  | void RunLoop::Quit() { | 
|  | quit_called_ = true; | 
|  | if (running_ && loop_->run_loop_ == this) { | 
|  | // This is the inner-most RunLoop, so quit now. | 
|  | loop_->QuitNow(); | 
|  | } | 
|  | } | 
|  |  | 
|  | base::Closure RunLoop::QuitClosure() { | 
|  | return base::Bind(&RunLoop::Quit, weak_factory_.GetWeakPtr()); | 
|  | } | 
|  |  | 
|  | bool RunLoop::BeforeRun() { | 
|  | DCHECK(!run_called_); | 
|  | run_called_ = true; | 
|  |  | 
|  | // Allow Quit to be called before Run. | 
|  | if (quit_called_) | 
|  | return false; | 
|  |  | 
|  | // Push RunLoop stack: | 
|  | previous_run_loop_ = loop_->run_loop_; | 
|  | run_depth_ = previous_run_loop_? previous_run_loop_->run_depth_ + 1 : 1; | 
|  | loop_->run_loop_ = this; | 
|  |  | 
|  | running_ = true; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void RunLoop::AfterRun() { | 
|  | running_ = false; | 
|  |  | 
|  | // Pop RunLoop stack: | 
|  | loop_->run_loop_ = previous_run_loop_; | 
|  |  | 
|  | // Execute deferred QuitNow, if any: | 
|  | if (previous_run_loop_ && previous_run_loop_->quit_called_) | 
|  | loop_->QuitNow(); | 
|  | } | 
|  |  | 
|  | }  // namespace base |