run_loop.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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      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)
28RunLoop::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
41RunLoop::~RunLoop() {
42}
43
44void RunLoop::Run() {
45  if (!BeforeRun())
46    return;
47  loop_->RunHandler();
48  AfterRun();
49}
50
51void RunLoop::RunUntilIdle() {
52  quit_when_idle_received_ = true;
53  Run();
54}
55
56void 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
64base::Closure RunLoop::QuitClosure() {
65  return base::Bind(&RunLoop::Quit, weak_factory_.GetWeakPtr());
66}
67
68bool 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
85void 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