blob: 0460b28d4973a71942b3dfb477c12e1b5e5e0645 [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// Copyright (c) 2006-2008 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/message_pump_default.h"
6
7#include "base/logging.h"
8
9namespace base {
10
11MessagePumpDefault::MessagePumpDefault()
12 : keep_running_(true),
13 event_(false, false) {
14}
15
16void MessagePumpDefault::Run(Delegate* delegate) {
17 DCHECK(keep_running_) << "Quit must have been called outside of Run!";
18
19 for (;;) {
20 bool did_work = delegate->DoWork();
21 if (!keep_running_)
22 break;
23 if (did_work)
24 continue;
25
26 // TODO(darin): Delayed work will be starved if DoWork continues to return
27 // true. We should devise a better strategy.
28 //
29 // It is tempting to call DoWork followed by DoDelayedWork before checking
30 // did_work, but we need to make sure that any tasks that were dispatched
31 // prior to a timer actually run before the timer. Getting that right may
32 // require some additional changes.
33
34 did_work = delegate->DoDelayedWork(&delayed_work_time_);
35 if (!keep_running_)
36 break;
37 if (did_work)
38 continue;
39
40 did_work = delegate->DoIdleWork();
41 if (!keep_running_)
42 break;
43 if (did_work)
44 continue;
45
46 if (delayed_work_time_.is_null()) {
47 event_.Wait();
48 } else {
49 TimeDelta delay = delayed_work_time_ - Time::Now();
50 if (delay > TimeDelta()) {
51 event_.TimedWait(delay);
52 } else {
53 // It looks like delayed_work_time_ indicates a time in the past, so we
54 // need to call DoDelayedWork now.
55 delayed_work_time_ = Time();
56 }
57 }
58 // Since event_ is auto-reset, we don't need to do anything special here
59 // other than service each delegate method.
60 }
61
62 keep_running_ = true;
63}
64
65void MessagePumpDefault::Quit() {
66 keep_running_ = false;
67}
68
69void MessagePumpDefault::ScheduleWork() {
70 // Since this can be called on any thread, we need to ensure that our Run
71 // loop wakes up.
72 event_.Signal();
73}
74
75void MessagePumpDefault::ScheduleDelayedWork(const Time& delayed_work_time) {
76 // We know that we can't be blocked on Wait right now since this method can
77 // only be called on the same thread as Run, so we only need to update our
78 // record of how long to sleep when we do sleep.
79 delayed_work_time_ = delayed_work_time;
80}
81
82} // namespace base
83