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