1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/run_loop.h" 6 7 #include "base/bind.h" 8 9 namespace base { 10 11 RunLoop::RunLoop() 12 : loop_(MessageLoop::current()), 13 previous_run_loop_(NULL), 14 run_depth_(0), 15 run_called_(false), 16 quit_called_(false), 17 running_(false), 18 quit_when_idle_received_(false), 19 weak_factory_(this) { 20 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \ 21 !defined(USE_GTK_MESSAGE_PUMP) 22 dispatcher_ = NULL; 23 #endif 24 } 25 26 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && \ 27 !defined(USE_GTK_MESSAGE_PUMP) 28 RunLoop::RunLoop(MessageLoop::Dispatcher* dispatcher) 29 : loop_(MessageLoop::current()), 30 previous_run_loop_(NULL), 31 dispatcher_(dispatcher), 32 run_depth_(0), 33 run_called_(false), 34 quit_called_(false), 35 running_(false), 36 quit_when_idle_received_(false), 37 weak_factory_(this) { 38 } 39 #endif 40 41 RunLoop::~RunLoop() { 42 } 43 44 void RunLoop::Run() { 45 if (!BeforeRun()) 46 return; 47 loop_->RunHandler(); 48 AfterRun(); 49 } 50 51 void RunLoop::RunUntilIdle() { 52 quit_when_idle_received_ = true; 53 Run(); 54 } 55 56 void RunLoop::Quit() { 57 quit_called_ = true; 58 if (running_ && loop_->run_loop_ == this) { 59 // This is the inner-most RunLoop, so quit now. 60 loop_->QuitNow(); 61 } 62 } 63 64 base::Closure RunLoop::QuitClosure() { 65 return base::Bind(&RunLoop::Quit, weak_factory_.GetWeakPtr()); 66 } 67 68 bool RunLoop::BeforeRun() { 69 DCHECK(!run_called_); 70 run_called_ = true; 71 72 // Allow Quit to be called before Run. 73 if (quit_called_) 74 return false; 75 76 // Push RunLoop stack: 77 previous_run_loop_ = loop_->run_loop_; 78 run_depth_ = previous_run_loop_? previous_run_loop_->run_depth_ + 1 : 1; 79 loop_->run_loop_ = this; 80 81 running_ = true; 82 return true; 83 } 84 85 void RunLoop::AfterRun() { 86 running_ = false; 87 88 // Pop RunLoop stack: 89 loop_->run_loop_ = previous_run_loop_; 90 91 // Execute deferred QuitNow, if any: 92 if (previous_run_loop_ && previous_run_loop_->quit_called_) 93 loop_->QuitNow(); 94 } 95 96 } // namespace base 97