message_pump_default.cc (3044B)
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 13 #include "mozilla/BackgroundHangMonitor.h" 14 #include "mozilla/ProfilerLabels.h" 15 #include "mozilla/ProfilerThreadSleep.h" 16 17 namespace base { 18 19 MessagePumpDefault::MessagePumpDefault() 20 : keep_running_(true), event_(false, false) {} 21 22 void MessagePumpDefault::Run(Delegate* delegate) { 23 AUTO_PROFILER_LABEL("MessagePumpDefault::Run", OTHER); 24 25 DCHECK(keep_running_) << "Quit must have been called outside of Run!"; 26 27 const MessageLoop* const loop = MessageLoop::current(); 28 mozilla::BackgroundHangMonitor hangMonitor(loop->thread_name().c_str(), 29 loop->transient_hang_timeout(), 30 loop->permanent_hang_timeout()); 31 32 for (;;) { 33 ScopedNSAutoreleasePool autorelease_pool; 34 35 hangMonitor.NotifyActivity(); 36 bool did_work = delegate->DoWork(); 37 if (!keep_running_) break; 38 39 hangMonitor.NotifyActivity(); 40 did_work |= delegate->DoDelayedWork(&delayed_work_time_); 41 if (!keep_running_) break; 42 43 if (did_work) continue; 44 45 hangMonitor.NotifyActivity(); 46 did_work = delegate->DoIdleWork(); 47 if (!keep_running_) break; 48 49 if (did_work) continue; 50 51 if (delayed_work_time_.is_null()) { 52 hangMonitor.NotifyWait(); 53 AUTO_PROFILER_LABEL("MessagePumpDefault::Run:Wait", IDLE); 54 { 55 AUTO_PROFILER_THREAD_SLEEP; 56 event_.Wait(); 57 } 58 } else { 59 TimeDelta delay = delayed_work_time_ - TimeTicks::Now(); 60 if (delay > TimeDelta()) { 61 hangMonitor.NotifyWait(); 62 AUTO_PROFILER_LABEL("MessagePumpDefault::Run:Wait", IDLE); 63 { 64 AUTO_PROFILER_THREAD_SLEEP; 65 event_.TimedWait(delay); 66 } 67 } else { 68 // It looks like delayed_work_time_ indicates a time in the past, so we 69 // need to call DoDelayedWork now. 70 delayed_work_time_ = TimeTicks(); 71 } 72 } 73 // Since event_ is auto-reset, we don't need to do anything special here 74 // other than service each delegate method. 75 } 76 77 keep_running_ = true; 78 } 79 80 void MessagePumpDefault::Quit() { keep_running_ = false; } 81 82 void MessagePumpDefault::ScheduleWork() { 83 // Since this can be called on any thread, we need to ensure that our Run 84 // loop wakes up. 85 event_.Signal(); 86 } 87 88 void MessagePumpDefault::ScheduleDelayedWork( 89 const TimeTicks& delayed_work_time) { 90 // We know that we can't be blocked on Wait right now since this method can 91 // only be called on the same thread as Run, so we only need to update our 92 // record of how long to sleep when we do sleep. 93 delayed_work_time_ = delayed_work_time; 94 } 95 96 } // namespace base