Home | History | Annotate | Download | only in message_loop
      1 // 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_loop/message_pump_default.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/threading/thread_restrictions.h"
      9 
     10 #if defined(OS_MACOSX)
     11 #include "base/mac/scoped_nsautorelease_pool.h"
     12 #endif
     13 
     14 namespace base {
     15 
     16 MessagePumpDefault::MessagePumpDefault()
     17     : keep_running_(true),
     18       event_(false, false) {
     19 }
     20 
     21 MessagePumpDefault::~MessagePumpDefault() {
     22 }
     23 
     24 void MessagePumpDefault::Run(Delegate* delegate) {
     25   DCHECK(keep_running_) << "Quit must have been called outside of Run!";
     26 
     27   for (;;) {
     28 #if defined(OS_MACOSX)
     29     mac::ScopedNSAutoreleasePool autorelease_pool;
     30 #endif
     31 
     32     bool did_work = delegate->DoWork();
     33     if (!keep_running_)
     34       break;
     35 
     36     did_work |= delegate->DoDelayedWork(&delayed_work_time_);
     37     if (!keep_running_)
     38       break;
     39 
     40     if (did_work)
     41       continue;
     42 
     43     did_work = delegate->DoIdleWork();
     44     if (!keep_running_)
     45       break;
     46 
     47     if (did_work)
     48       continue;
     49 
     50     ThreadRestrictions::ScopedAllowWait allow_wait;
     51     if (delayed_work_time_.is_null()) {
     52       event_.Wait();
     53     } else {
     54       TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
     55       if (delay > TimeDelta()) {
     56         event_.TimedWait(delay);
     57       } else {
     58         // It looks like delayed_work_time_ indicates a time in the past, so we
     59         // need to call DoDelayedWork now.
     60         delayed_work_time_ = TimeTicks();
     61       }
     62     }
     63     // Since event_ is auto-reset, we don't need to do anything special here
     64     // other than service each delegate method.
     65   }
     66 
     67   keep_running_ = true;
     68 }
     69 
     70 void MessagePumpDefault::Quit() {
     71   keep_running_ = false;
     72 }
     73 
     74 void MessagePumpDefault::ScheduleWork() {
     75   // Since this can be called on any thread, we need to ensure that our Run
     76   // loop wakes up.
     77   event_.Signal();
     78 }
     79 
     80 void MessagePumpDefault::ScheduleDelayedWork(
     81     const TimeTicks& delayed_work_time) {
     82   // We know that we can't be blocked on Wait right now since this method can
     83   // only be called on the same thread as Run, so we only need to update our
     84   // record of how long to sleep when we do sleep.
     85   delayed_work_time_ = delayed_work_time;
     86 }
     87 
     88 }  // namespace base
     89