blob: 8344aa41b1631f6946e242e9ef0efbafdee23279 [file] [log] [blame]
jbates@chromium.org5d5b2812012-06-29 07:57:30 +09001// 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
sadrul@chromium.org9f651a52014-04-16 14:29:49 +09009#if defined(OS_WIN)
sky@chromium.org66a00b32014-01-17 09:10:29 +090010#include "base/message_loop/message_pump_dispatcher.h"
11#endif
12
jbates@chromium.org5d5b2812012-06-29 07:57:30 +090013namespace base {
14
15RunLoop::RunLoop()
16 : loop_(MessageLoop::current()),
jbates@chromium.org5d5b2812012-06-29 07:57:30 +090017 previous_run_loop_(NULL),
18 run_depth_(0),
19 run_called_(false),
20 quit_called_(false),
21 running_(false),
dmichael@chromium.org4f8c55b2013-10-09 04:23:33 +090022 quit_when_idle_received_(false),
23 weak_factory_(this) {
sadrul@chromium.orgbe4515c2014-04-06 00:24:03 +090024#if defined(OS_WIN)
jbates@chromium.org5d5b2812012-06-29 07:57:30 +090025 dispatcher_ = NULL;
26#endif
27}
28
sadrul@chromium.orgbe4515c2014-04-06 00:24:03 +090029#if defined(OS_WIN)
sky@chromium.org66a00b32014-01-17 09:10:29 +090030RunLoop::RunLoop(MessagePumpDispatcher* dispatcher)
jbates@chromium.org5d5b2812012-06-29 07:57:30 +090031 : loop_(MessageLoop::current()),
jbates@chromium.org5d5b2812012-06-29 07:57:30 +090032 previous_run_loop_(NULL),
33 dispatcher_(dispatcher),
34 run_depth_(0),
35 run_called_(false),
36 quit_called_(false),
37 running_(false),
dmichael@chromium.org4f8c55b2013-10-09 04:23:33 +090038 quit_when_idle_received_(false),
39 weak_factory_(this) {
jbates@chromium.org5d5b2812012-06-29 07:57:30 +090040}
41#endif
42
43RunLoop::~RunLoop() {
44}
45
46void RunLoop::Run() {
47 if (!BeforeRun())
48 return;
49 loop_->RunHandler();
50 AfterRun();
51}
52
53void RunLoop::RunUntilIdle() {
54 quit_when_idle_received_ = true;
55 Run();
56}
57
58void 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
66base::Closure RunLoop::QuitClosure() {
67 return base::Bind(&RunLoop::Quit, weak_factory_.GetWeakPtr());
68}
69
70bool 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
87void 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