Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
4 : // Use of this source code is governed by a BSD-style license that can be
5 : // found in the LICENSE file.
6 :
7 : #include "base/message_pump_default.h"
8 :
9 : #include "base/logging.h"
10 : #include "base/message_loop.h"
11 : #include "base/scoped_nsautorelease_pool.h"
12 : #include "GeckoProfiler.h"
13 :
14 : #include "mozilla/BackgroundHangMonitor.h"
15 :
16 : namespace base {
17 :
18 64 : MessagePumpDefault::MessagePumpDefault()
19 : : keep_running_(true),
20 64 : event_(false, false) {
21 64 : }
22 :
23 5 : void MessagePumpDefault::Run(Delegate* delegate) {
24 5 : DCHECK(keep_running_) << "Quit must have been called outside of Run!";
25 :
26 5 : const MessageLoop* const loop = MessageLoop::current();
27 : mozilla::BackgroundHangMonitor hangMonitor(
28 5 : loop->thread_name().c_str(),
29 : loop->transient_hang_timeout(),
30 10 : loop->permanent_hang_timeout());
31 :
32 : for (;;) {
33 2175 : ScopedNSAutoreleasePool autorelease_pool;
34 :
35 2175 : hangMonitor.NotifyActivity();
36 2175 : bool did_work = delegate->DoWork();
37 2175 : if (!keep_running_)
38 0 : break;
39 :
40 2175 : hangMonitor.NotifyActivity();
41 2175 : did_work |= delegate->DoDelayedWork(&delayed_work_time_);
42 2174 : if (!keep_running_)
43 0 : break;
44 :
45 2174 : if (did_work)
46 1690 : continue;
47 :
48 1329 : hangMonitor.NotifyActivity();
49 1329 : did_work = delegate->DoIdleWork();
50 1329 : if (!keep_running_)
51 0 : break;
52 :
53 1329 : if (did_work)
54 0 : continue;
55 :
56 1329 : if (delayed_work_time_.is_null()) {
57 280 : hangMonitor.NotifyWait();
58 555 : AUTO_PROFILER_LABEL("MessagePumpDefault::Run:Wait", OTHER);
59 : {
60 555 : mozilla::AutoProfilerThreadSleep sleep;
61 280 : event_.Wait();
62 : }
63 : } else {
64 1050 : TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
65 1050 : if (delay > TimeDelta()) {
66 1050 : hangMonitor.NotifyWait();
67 2100 : AUTO_PROFILER_LABEL("MessagePumpDefault::Run:Wait", OTHER);
68 : {
69 2100 : mozilla::AutoProfilerThreadSleep sleep;
70 1050 : event_.TimedWait(delay);
71 : }
72 : } else {
73 : // It looks like delayed_work_time_ indicates a time in the past, so we
74 : // need to call DoDelayedWork now.
75 0 : delayed_work_time_ = TimeTicks();
76 : }
77 : }
78 : // Since event_ is auto-reset, we don't need to do anything special here
79 : // other than service each delegate method.
80 2170 : }
81 :
82 0 : keep_running_ = true;
83 0 : }
84 :
85 1 : void MessagePumpDefault::Quit() {
86 1 : keep_running_ = false;
87 1 : }
88 :
89 845 : void MessagePumpDefault::ScheduleWork() {
90 : // Since this can be called on any thread, we need to ensure that our Run
91 : // loop wakes up.
92 845 : event_.Signal();
93 845 : }
94 :
95 522 : void MessagePumpDefault::ScheduleDelayedWork(
96 : const TimeTicks& delayed_work_time) {
97 : // We know that we can't be blocked on Wait right now since this method can
98 : // only be called on the same thread as Run, so we only need to update our
99 : // record of how long to sleep when we do sleep.
100 522 : delayed_work_time_ = delayed_work_time;
101 522 : }
102 :
103 : } // namespace base
|