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