// 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" #include "build/build_config.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