Home | History | Annotate | Download | only in base
      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