|  | // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/message_loop/message_pump_default.h" | 
|  |  | 
|  | #include "base/logging.h" | 
|  | #include "base/threading/thread_restrictions.h" | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  | #include "base/mac/scoped_nsautorelease_pool.h" | 
|  | #endif | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | MessagePumpDefault::MessagePumpDefault() | 
|  | : keep_running_(true), | 
|  | event_(false, false) { | 
|  | } | 
|  |  | 
|  | MessagePumpDefault::~MessagePumpDefault() { | 
|  | } | 
|  |  | 
|  | void MessagePumpDefault::Run(Delegate* delegate) { | 
|  | DCHECK(keep_running_) << "Quit must have been called outside of Run!"; | 
|  |  | 
|  | for (;;) { | 
|  | #if defined(OS_MACOSX) | 
|  | mac::ScopedNSAutoreleasePool autorelease_pool; | 
|  | #endif | 
|  |  | 
|  | bool did_work = delegate->DoWork(); | 
|  | if (!keep_running_) | 
|  | break; | 
|  |  | 
|  | did_work |= delegate->DoDelayedWork(&delayed_work_time_); | 
|  | if (!keep_running_) | 
|  | break; | 
|  |  | 
|  | if (did_work) | 
|  | continue; | 
|  |  | 
|  | did_work = delegate->DoIdleWork(); | 
|  | if (!keep_running_) | 
|  | break; | 
|  |  | 
|  | if (did_work) | 
|  | continue; | 
|  |  | 
|  | ThreadRestrictions::ScopedAllowWait allow_wait; | 
|  | if (delayed_work_time_.is_null()) { | 
|  | event_.Wait(); | 
|  | } else { | 
|  | TimeDelta delay = delayed_work_time_ - TimeTicks::Now(); | 
|  | if (delay > TimeDelta()) { | 
|  | event_.TimedWait(delay); | 
|  | } else { | 
|  | // It looks like delayed_work_time_ indicates a time in the past, so we | 
|  | // need to call DoDelayedWork now. | 
|  | delayed_work_time_ = TimeTicks(); | 
|  | } | 
|  | } | 
|  | // Since event_ is auto-reset, we don't need to do anything special here | 
|  | // other than service each delegate method. | 
|  | } | 
|  |  | 
|  | keep_running_ = true; | 
|  | } | 
|  |  | 
|  | void MessagePumpDefault::Quit() { | 
|  | keep_running_ = false; | 
|  | } | 
|  |  | 
|  | void MessagePumpDefault::ScheduleWork() { | 
|  | // Since this can be called on any thread, we need to ensure that our Run | 
|  | // loop wakes up. | 
|  | event_.Signal(); | 
|  | } | 
|  |  | 
|  | void MessagePumpDefault::ScheduleDelayedWork( | 
|  | const TimeTicks& delayed_work_time) { | 
|  | // We know that we can't be blocked on Wait right now since this method can | 
|  | // only be called on the same thread as Run, so we only need to update our | 
|  | // record of how long to sleep when we do sleep. | 
|  | delayed_work_time_ = delayed_work_time; | 
|  | } | 
|  |  | 
|  | }  // namespace base |