diff options
author | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-20 01:13:40 +0000 |
---|---|---|
committer | darin@google.com <darin@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-08-20 01:13:40 +0000 |
commit | 3816f46725f7b8e42e352a063efd5206a46dbe9a (patch) | |
tree | d64edfcf741dcd927ce404f66dab723e8a0914c8 /base | |
parent | bda05798c0609582075a3b872c37ad56021920c4 (diff) | |
download | chromium_src-3816f46725f7b8e42e352a063efd5206a46dbe9a.zip chromium_src-3816f46725f7b8e42e352a063efd5206a46dbe9a.tar.gz chromium_src-3816f46725f7b8e42e352a063efd5206a46dbe9a.tar.bz2 |
rollback r1075 to see if it helps resolve test failures
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1078 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/message_loop.cc | 12 | ||||
-rw-r--r-- | base/message_loop.h | 2 | ||||
-rw-r--r-- | base/message_pump.h | 17 | ||||
-rw-r--r-- | base/message_pump_default.cc | 30 | ||||
-rw-r--r-- | base/message_pump_default.h | 5 | ||||
-rw-r--r-- | base/message_pump_win.cc | 37 | ||||
-rw-r--r-- | base/message_pump_win.h | 2 | ||||
-rw-r--r-- | base/timer.cc | 20 | ||||
-rw-r--r-- | base/timer.h | 10 | ||||
-rw-r--r-- | base/waitable_event_win.cc | 9 |
10 files changed, 63 insertions, 81 deletions
diff --git a/base/message_loop.cc b/base/message_loop.cc index eb10ca7..4964dfe 100644 --- a/base/message_loop.cc +++ b/base/message_loop.cc @@ -386,16 +386,16 @@ void MessageLoop::DeletePendingTasks() { } void MessageLoop::DidChangeNextTimerExpiry() { - Time next_delayed_work_time = timer_manager_.GetNextFireTime(); - if (next_delayed_work_time.is_null()) + int delay = timer_manager_.GetCurrentDelay(); + if (delay == -1) return; // Simulates malfunctioning, early firing timers. Pending tasks should only // be invoked when the delay they specify has elapsed. if (timer_manager_.use_broken_delay()) - next_delayed_work_time = Time::Now() + TimeDelta::FromMilliseconds(10); + delay = 10; - pump_->ScheduleDelayedWork(next_delayed_work_time); + pump_->ScheduleDelayedWork(TimeDelta::FromMilliseconds(delay)); } bool MessageLoop::DoWork() { @@ -403,12 +403,12 @@ bool MessageLoop::DoWork() { return QueueOrRunTask(NULL); } -bool MessageLoop::DoDelayedWork(Time* next_delayed_work_time) { +bool MessageLoop::DoDelayedWork(TimeDelta* next_delay) { bool did_work = timer_manager_.RunSomePendingTimers(); // We may not have run any timers, but we may still have future timers to // run, so we need to inform the pump again of pending timers. - *next_delayed_work_time = timer_manager_.GetNextFireTime(); + *next_delay = TimeDelta::FromMilliseconds(timer_manager_.GetCurrentDelay()); return did_work; } diff --git a/base/message_loop.h b/base/message_loop.h index 3821519..afcab64 100644 --- a/base/message_loop.h +++ b/base/message_loop.h @@ -415,7 +415,7 @@ class MessageLoop : public base::MessagePump::Delegate { // base::MessagePump::Delegate methods: virtual bool DoWork(); - virtual bool DoDelayedWork(Time* next_delayed_work_time); + virtual bool DoDelayedWork(TimeDelta* next_delay); virtual bool DoIdleWork(); // Start recording histogram info about events and action IF it was enabled diff --git a/base/message_pump.h b/base/message_pump.h index 06cef43..a06a435 100644 --- a/base/message_pump.h +++ b/base/message_pump.h @@ -32,7 +32,7 @@ #include "base/ref_counted.h" -class Time; +class TimeDelta; namespace base { @@ -52,12 +52,11 @@ class MessagePump : public RefCountedThreadSafe<MessagePump> { // Called from within Run in response to ScheduleDelayedWork or when the // message pump would otherwise sleep waiting for more work. Returns true // to indicate that delayed work was done. DoIdleWork will not be called - // if DoDelayedWork returns true. Upon return |next_delayed_work_time| - // indicates the time when DoDelayedWork should be called again. If - // |next_delayed_work_time| is null (per Time::is_null), then the queue of - // future delayed work (timer events) is currently empty, and no additional - // calls to this function need to be scheduled. - virtual bool DoDelayedWork(Time* next_delayed_work_time) = 0; + // if DoDelayedWork returns true. Upon return |next_delay| indicates the + // next delayed work interval. If |next_delay| is negative, then the queue + // of future delayed work (timer events) is currently empty, and no + // additional calls to this function need to be scheduled. + virtual bool DoDelayedWork(TimeDelta* next_delay) = 0; // Called from within Run just before the message pump goes to sleep. // Returns true to indicate that idle work was done. @@ -138,10 +137,10 @@ class MessagePump : public RefCountedThreadSafe<MessagePump> { // until it returns a value of false. virtual void ScheduleWork() = 0; - // Schedule a DoDelayedWork callback to happen at the specified time, + // Schedule a DoDelayedWork callback to happen after the specified delay, // cancelling any pending DoDelayedWork callback. This method may only be // used on the thread that called Run. - virtual void ScheduleDelayedWork(const Time& delayed_work_time) = 0; + virtual void ScheduleDelayedWork(const TimeDelta& delay) = 0; }; } // namespace base diff --git a/base/message_pump_default.cc b/base/message_pump_default.cc index a45f480..916d035 100644 --- a/base/message_pump_default.cc +++ b/base/message_pump_default.cc @@ -51,13 +51,9 @@ void MessagePumpDefault::Run(Delegate* delegate) { // TODO(darin): Delayed work will be starved if DoWork continues to return // true. We should devise a better strategy. - // - // It is tempting to call DoWork followed by DoDelayedWork before checking - // did_work, but we need to make sure that any tasks that were dispatched - // prior to a timer actually run before the timer. Getting that right may - // require some additional changes. - did_work = delegate->DoDelayedWork(&delayed_work_time_); + TimeDelta delay; + did_work = delegate->DoDelayedWork(&delay); if (!keep_running_) break; if (did_work) @@ -68,18 +64,13 @@ void MessagePumpDefault::Run(Delegate* delegate) { break; if (did_work) continue; + // When DoIdleWork does not work, we also assume that it ran very quickly + // such that |delay| still properly indicates how long we are to sleep. - if (delayed_work_time_.is_null()) { + if (delay < TimeDelta::FromMilliseconds(0)) { event_.Wait(); } else { - TimeDelta delay = delayed_work_time_ - Time::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_ = Time(); - } + event_.TimedWait(delay); } // Since event_ is auto-reset, we don't need to do anything special here // other than service each delegate method. @@ -98,11 +89,12 @@ void MessagePumpDefault::ScheduleWork() { event_.Signal(); } -void MessagePumpDefault::ScheduleDelayedWork(const Time& delayed_work_time) { +void MessagePumpDefault::ScheduleDelayedWork(const TimeDelta& delay) { // 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; + // only be called on the same thread as Run, but to ensure that when we do + // sleep, we sleep for the right time, we signal the event to cause the Run + // loop to do one more iteration. + event_.Signal(); } } // namespace base diff --git a/base/message_pump_default.h b/base/message_pump_default.h index 7c65013..1c1af71 100644 --- a/base/message_pump_default.h +++ b/base/message_pump_default.h @@ -44,7 +44,7 @@ class MessagePumpDefault : public MessagePump { virtual void Run(Delegate* delegate); virtual void Quit(); virtual void ScheduleWork(); - virtual void ScheduleDelayedWork(const Time& delayed_work_time); + virtual void ScheduleDelayedWork(const TimeDelta& delay); private: // This flag is set to false when Run should return. @@ -53,9 +53,6 @@ class MessagePumpDefault : public MessagePump { // Used to sleep until there is more work to do. WaitableEvent event_; - // The time at which we should call DoDelayedWork. - Time delayed_work_time_; - DISALLOW_COPY_AND_ASSIGN(MessagePumpDefault); }; diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc index 28191ea..f290e44 100644 --- a/base/message_pump_win.cc +++ b/base/message_pump_win.cc @@ -29,8 +29,6 @@ #include "base/message_pump_win.h" -#include <math.h> - #include "base/histogram.h" #include "base/win_util.h" @@ -162,7 +160,7 @@ void MessagePumpWin::ScheduleWork() { PostMessage(message_hwnd_, kMsgHaveWork, reinterpret_cast<WPARAM>(this), 0); } -void MessagePumpWin::ScheduleDelayedWork(const Time& delayed_work_time) { +void MessagePumpWin::ScheduleDelayedWork(const TimeDelta& delay) { // // We would *like* to provide high resolution timers. Windows timers using // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup @@ -183,9 +181,7 @@ void MessagePumpWin::ScheduleDelayedWork(const Time& delayed_work_time) { // Getting a spurrious SetTimer event firing is benign, as we'll just be // processing an empty timer queue. // - delayed_work_time_ = delayed_work_time; - - int delay_msec = GetCurrentDelay(); + int delay_msec = static_cast<int>(delay.InMilliseconds()); DCHECK(delay_msec >= 0); if (delay_msec < USER_TIMER_MINIMUM) delay_msec = USER_TIMER_MINIMUM; @@ -254,11 +250,10 @@ void MessagePumpWin::HandleTimerMessage() { if (!state_) return; - state_->delegate->DoDelayedWork(&delayed_work_time_); - if (!delayed_work_time_.is_null()) { - // A bit gratuitous to set delayed_work_time_ again, but oh well. - ScheduleDelayedWork(delayed_work_time_); - } + TimeDelta next_delay; + state_->delegate->DoDelayedWork(&next_delay); + if (next_delay >= TimeDelta::FromMilliseconds(0)) + ScheduleDelayedWork(next_delay); } void MessagePumpWin::DoRunLoop() { @@ -300,13 +295,14 @@ void MessagePumpWin::DoRunLoop() { if (more_work_is_plausible) continue; - more_work_is_plausible = - state_->delegate->DoDelayedWork(&delayed_work_time_); + TimeDelta next_delay; + more_work_is_plausible = state_->delegate->DoDelayedWork(&next_delay); // If we did not process any delayed work, then we can assume that our // existing WM_TIMER if any will fire when delayed work should run. We // don't want to disturb that timer if it is already in flight. However, // if we did do all remaining delayed work, then lets kill the WM_TIMER. - if (more_work_is_plausible && delayed_work_time_.is_null()) + if (more_work_is_plausible && + next_delay < TimeDelta::FromMilliseconds(0)) KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); if (state_->should_quit) break; @@ -523,17 +519,8 @@ int MessagePumpWin::GetCurrentDelay() const { if (delayed_work_time_.is_null()) return -1; - // Be careful here. TimeDelta has a precision of microseconds, but we want a - // value in milliseconds. If there are 5.5ms left, should the delay be 5 or - // 6? It should be 6 to avoid executing delayed work too early. - double timeout = ceil((Time::Now() - delayed_work_time_).InMillisecondsF()); - - // If this value is negative, then we need to run delayed work soon. - int delay = static_cast<int>(timeout); - if (delay < 0) - delay = 0; - - return delay; + // This could be a negative value, but that's OK. + return static_cast<int>((Time::Now() - delayed_work_time_).InMilliseconds()); } } // namespace base diff --git a/base/message_pump_win.h b/base/message_pump_win.h index ff021e3..6699fde 100644 --- a/base/message_pump_win.h +++ b/base/message_pump_win.h @@ -161,7 +161,7 @@ class MessagePumpWin : public MessagePump { virtual void Run(Delegate* delegate) { RunWithDispatcher(delegate, NULL); } virtual void Quit(); virtual void ScheduleWork(); - virtual void ScheduleDelayedWork(const Time& delayed_work_time); + virtual void ScheduleDelayedWork(const TimeDelta& delay); private: struct RunState { diff --git a/base/timer.cc b/base/timer.cc index aced8cb..46fae6e 100644 --- a/base/timer.cc +++ b/base/timer.cc @@ -55,6 +55,14 @@ Timer::Timer(int delay, Task* task, bool repeating) Reset(); } +int Timer::GetCurrentDelay() const { + // Be careful here. Timers have a precision of microseconds, but this API is + // in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? It + // should be 6 to avoid timers firing early. + double delay = ceil((fire_time_ - Time::Now()).InMillisecondsF()); + return static_cast<int>(delay); +} + void Timer::Reset() { creation_time_ = Time::Now(); fire_time_ = creation_time_ + TimeDelta::FromMilliseconds(delay_); @@ -155,7 +163,7 @@ bool TimerManager::RunSomePendingTimers() { // timers have been set. const int kMaxTimersPerCall = 2; for (int i = 0; i < kMaxTimersPerCall; ++i) { - if (timers_.empty() || timers_.top()->fire_time() > Time::Now()) + if (timers_.empty() || GetCurrentDelay() > 0) break; // Get a pending timer. Deal with updating the timers_ queue and setting @@ -203,11 +211,13 @@ void TimerManager::StartTimer(Timer* timer) { DidChangeNextTimer(); } -Time TimerManager::GetNextFireTime() const { +int TimerManager::GetCurrentDelay() { if (timers_.empty()) - return Time(); - - return timers_.top()->fire_time(); + return -1; + int delay = timers_.top()->GetCurrentDelay(); + if (delay < 0) + delay = 0; + return delay; } void TimerManager::DidChangeNextTimer() { diff --git a/base/timer.h b/base/timer.h index 74fe27b..c23f725 100644 --- a/base/timer.h +++ b/base/timer.h @@ -59,6 +59,9 @@ class Timer { Task* task() const { return task_; } void set_task(Task* task) { task_ = task; } + // Returns the time in msec relative to now that the timer should fire. + int GetCurrentDelay() const; + // Returns the absolute time at which the timer should fire. const Time &fire_time() const { return fire_time_; } @@ -174,10 +177,9 @@ class TimerManager { // Returns true if it runs a task, false otherwise. bool RunSomePendingTimers(); - // The absolute time at which the next timer is to fire. If there is not a - // next timer to run, then the is_null property of the returned Time object - // will be true. NOTE: This could be a time in the past! - Time GetNextFireTime() const; + // The number of milliseconds remaining until the pending timer (top of the + // pqueue) needs to be fired. Returns -1 if no timers are pending. + int GetCurrentDelay(); #ifdef UNIT_TEST // For testing only, used to simulate broken early-firing WM_TIMER diff --git a/base/waitable_event_win.cc b/base/waitable_event_win.cc index e23eea0..da2d2d8 100644 --- a/base/waitable_event_win.cc +++ b/base/waitable_event_win.cc @@ -29,7 +29,6 @@ #include "base/waitable_event.h" -#include <math.h> #include <windows.h> #include "base/logging.h" @@ -69,12 +68,8 @@ bool WaitableEvent::Wait() { } bool WaitableEvent::TimedWait(const TimeDelta& max_time) { - DCHECK(max_time >= TimeDelta::FromMicroseconds(0)); - // Be careful here. TimeDelta has a precision of microseconds, but this API - // is in milliseconds. If there are 5.5ms left, should the delay be 5 or 6? - // It should be 6 to avoid returning too early. - double timeout = ceil(max_time.InMillisecondsF()); - DWORD result = WaitForSingleObject(event_, static_cast<DWORD>(timeout)); + int32 timeout = static_cast<int32>(max_time.InMilliseconds()); + DWORD result = WaitForSingleObject(event_, timeout); switch (result) { case WAIT_OBJECT_0: return true; |