blob: 4c19d3589fd7e6f893a7a02f91d2c5a2371720ec [file] [log] [blame]
[email protected]8e937c1e2012-06-28 22:57:301// 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"
vadimt12f0f7d2014-09-15 19:19:388#include "base/tracked_objects.h"
avi9b6f42932015-12-26 22:15:149#include "build/build_config.h"
[email protected]8e937c1e2012-06-28 22:57:3010
11namespace base {
12
13RunLoop::RunLoop()
14 : loop_(MessageLoop::current()),
[email protected]8e937c1e2012-06-28 22:57:3015 previous_run_loop_(NULL),
16 run_depth_(0),
17 run_called_(false),
18 quit_called_(false),
19 running_(false),
[email protected]dcf10632013-10-08 19:23:3320 quit_when_idle_received_(false),
21 weak_factory_(this) {
ahest68c9f102016-12-13 11:34:3822 DCHECK(loop_);
[email protected]8e937c1e2012-06-28 22:57:3023}
24
[email protected]8e937c1e2012-06-28 22:57:3025RunLoop::~RunLoop() {
26}
27
28void RunLoop::Run() {
ahest72c1b442016-12-09 20:40:3829 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]8e937c1e2012-06-28 22:57:3030 if (!BeforeRun())
31 return;
vadimt12f0f7d2014-09-15 19:19:3832
33 // Use task stopwatch to exclude the loop run time from the current task, if
34 // any.
35 tracked_objects::TaskStopwatch stopwatch;
vadimt20175532014-10-28 20:14:2036 stopwatch.Start();
[email protected]8e937c1e2012-06-28 22:57:3037 loop_->RunHandler();
vadimt12f0f7d2014-09-15 19:19:3838 stopwatch.Stop();
39
[email protected]8e937c1e2012-06-28 22:57:3040 AfterRun();
41}
42
43void RunLoop::RunUntilIdle() {
44 quit_when_idle_received_ = true;
45 Run();
46}
47
48void RunLoop::Quit() {
ahest72c1b442016-12-09 20:40:3849 DCHECK(thread_checker_.CalledOnValidThread());
[email protected]8e937c1e2012-06-28 22:57:3050 quit_called_ = true;
51 if (running_ && loop_->run_loop_ == this) {
52 // This is the inner-most RunLoop, so quit now.
53 loop_->QuitNow();
54 }
55}
56
fdoraya4f28ec2016-06-10 00:08:5857void RunLoop::QuitWhenIdle() {
ahest72c1b442016-12-09 20:40:3858 DCHECK(thread_checker_.CalledOnValidThread());
fdoraya4f28ec2016-06-10 00:08:5859 quit_when_idle_received_ = true;
60}
61
[email protected]8e937c1e2012-06-28 22:57:3062base::Closure RunLoop::QuitClosure() {
63 return base::Bind(&RunLoop::Quit, weak_factory_.GetWeakPtr());
64}
65
fdoraya3658602016-06-10 18:23:1566base::Closure RunLoop::QuitWhenIdleClosure() {
67 return base::Bind(&RunLoop::QuitWhenIdle, weak_factory_.GetWeakPtr());
68}
69
[email protected]8e937c1e2012-06-28 22:57:3070bool 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
jamescookaacdfd02016-04-28 00:50:0383 if (run_depth_ > 1)
84 loop_->NotifyBeginNestedLoop();
85
[email protected]8e937c1e2012-06-28 22:57:3086 running_ = true;
87 return true;
88}
89
90void RunLoop::AfterRun() {
91 running_ = false;
92
93 // Pop RunLoop stack:
94 loop_->run_loop_ = previous_run_loop_;
95
96 // Execute deferred QuitNow, if any:
97 if (previous_run_loop_ && previous_run_loop_->quit_called_)
98 loop_->QuitNow();
99}
100
101} // namespace base