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 #include "base/tracked_objects.h"
      9 #include "build/build_config.h"
     10 
     11 #if defined(OS_WIN)
     12 #include "base/message_loop/message_pump_dispatcher.h"
     13 #endif
     14 
     15 namespace base {
     16 
     17 RunLoop::RunLoop()
     18     : loop_(MessageLoop::current()),
     19       previous_run_loop_(NULL),
     20       run_depth_(0),
     21       run_called_(false),
     22       quit_called_(false),
     23       running_(false),
     24       quit_when_idle_received_(false),
     25       weak_factory_(this) {
     26 #if defined(OS_WIN)
     27    dispatcher_ = NULL;
     28 #endif
     29 }
     30 
     31 #if defined(OS_WIN)
     32 RunLoop::RunLoop(MessagePumpDispatcher* dispatcher)
     33     : loop_(MessageLoop::current()),
     34       previous_run_loop_(NULL),
     35       dispatcher_(dispatcher),
     36       run_depth_(0),
     37       run_called_(false),
     38       quit_called_(false),
     39       running_(false),
     40       quit_when_idle_received_(false),
     41       weak_factory_(this) {
     42 }
     43 #endif
     44 
     45 RunLoop::~RunLoop() {
     46 }
     47 
     48 void RunLoop::Run() {
     49   if (!BeforeRun())
     50     return;
     51 
     52   // Use task stopwatch to exclude the loop run time from the current task, if
     53   // any.
     54   tracked_objects::TaskStopwatch stopwatch;
     55   stopwatch.Start();
     56   loop_->RunHandler();
     57   stopwatch.Stop();
     58 
     59   AfterRun();
     60 }
     61 
     62 void RunLoop::RunUntilIdle() {
     63   quit_when_idle_received_ = true;
     64   Run();
     65 }
     66 
     67 void RunLoop::Quit() {
     68   quit_called_ = true;
     69   if (running_ && loop_->run_loop_ == this) {
     70     // This is the inner-most RunLoop, so quit now.
     71     loop_->QuitNow();
     72   }
     73 }
     74 
     75 base::Closure RunLoop::QuitClosure() {
     76   return base::Bind(&RunLoop::Quit, weak_factory_.GetWeakPtr());
     77 }
     78 
     79 bool RunLoop::BeforeRun() {
     80   DCHECK(!run_called_);
     81   run_called_ = true;
     82 
     83   // Allow Quit to be called before Run.
     84   if (quit_called_)
     85     return false;
     86 
     87   // Push RunLoop stack:
     88   previous_run_loop_ = loop_->run_loop_;
     89   run_depth_ = previous_run_loop_? previous_run_loop_->run_depth_ + 1 : 1;
     90   loop_->run_loop_ = this;
     91 
     92   running_ = true;
     93   return true;
     94 }
     95 
     96 void RunLoop::AfterRun() {
     97   running_ = false;
     98 
     99   // Pop RunLoop stack:
    100   loop_->run_loop_ = previous_run_loop_;
    101 
    102   // Execute deferred QuitNow, if any:
    103   if (previous_run_loop_ && previous_run_loop_->quit_called_)
    104     loop_->QuitNow();
    105 }
    106 
    107 }  // namespace base
    108