Index: base/message_loop/message_pump_win.cc |
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc |
index 27b47e1a0f878cfceef3c04b2364116ca64ac4c8..226747e5ab855bd64c8ea36b01f9cdb905e3c7dd 100644 |
--- a/base/message_loop/message_pump_win.cc |
+++ b/base/message_loop/message_pump_win.cc |
@@ -122,44 +122,8 @@ void MessagePumpForUI::ScheduleWork() { |
} |
void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
- // |
- // 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 |
- // mechanism because the application can enter modal windows loops where it |
- // is not running our MessageLoop; the only way to have our timers fire in |
- // these cases is to post messages there. |
- // |
- // To provide sub-10ms timers, we process timers directly from our run loop. |
- // For the common case, timers will be processed there as the run loop does |
- // its normal work. However, we *also* set the system timer so that WM_TIMER |
- // events fire. This mops up the case of timers not being able to work in |
- // modal message loops. It is possible for the SetTimer to pop and have no |
- // pending timers, because they could have already been processed by the |
- // run loop itself. |
- // |
- // We use a single SetTimer corresponding to the timer that will expire |
- // soonest. As new timers are created and destroyed, we update SetTimer. |
- // 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(); |
- DCHECK_GE(delay_msec, 0); |
- if (delay_msec < USER_TIMER_MINIMUM) |
- delay_msec = USER_TIMER_MINIMUM; |
- |
- // Create a WM_TIMER event that will wake us up to check for any pending |
- // timers (in case we are running within a nested, external sub-pump). |
- BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), |
- delay_msec, NULL); |
- if (ret) |
- return; |
- // If we can't set timers, we are in big trouble... but cross our fingers for |
- // now. |
- // TODO(jar): If we don't see this error, use a CHECK() here instead. |
- UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, |
- MESSAGE_LOOP_PROBLEM_MAX); |
+ RescheduleTimer(); |
} |
//----------------------------------------------------------------------------- |
@@ -318,6 +282,8 @@ void MessagePumpForUI::HandleWorkMessage() { |
// needs to do more work. |
if (state_->delegate->DoWork()) |
ScheduleWork(); |
+ state_->delegate->DoDelayedWork(&delayed_work_time_); |
+ RescheduleTimer(); |
} |
void MessagePumpForUI::HandleTimerMessage() { |
@@ -330,9 +296,51 @@ void MessagePumpForUI::HandleTimerMessage() { |
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_); |
+ RescheduleTimer(); |
+} |
+ |
+void MessagePumpForUI::RescheduleTimer() { |
+ if (delayed_work_time_.is_null()) |
+ return; |
+ // |
+ // 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 |
+ // mechanism because the application can enter modal windows loops where it |
+ // is not running our MessageLoop; the only way to have our timers fire in |
+ // these cases is to post messages there. |
+ // |
+ // To provide sub-10ms timers, we process timers directly from our run loop. |
+ // For the common case, timers will be processed there as the run loop does |
+ // its normal work. However, we *also* set the system timer so that WM_TIMER |
+ // events fire. This mops up the case of timers not being able to work in |
+ // modal message loops. It is possible for the SetTimer to pop and have no |
+ // pending timers, because they could have already been processed by the |
+ // run loop itself. |
+ // |
+ // We use a single SetTimer corresponding to the timer that will expire |
+ // soonest. As new timers are created and destroyed, we update SetTimer. |
+ // Getting a spurrious SetTimer event firing is benign, as we'll just be |
+ // processing an empty timer queue. |
+ // |
+ int delay_msec = GetCurrentDelay(); |
+ DCHECK_GE(delay_msec, 0); |
+ if (delay_msec == 0) { |
+ ScheduleWork(); |
+ } else { |
+ if (delay_msec < USER_TIMER_MINIMUM) |
+ delay_msec = USER_TIMER_MINIMUM; |
+ |
+ // Create a WM_TIMER event that will wake us up to check for any pending |
+ // timers (in case we are running within a nested, external sub-pump). |
+ BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), |
+ delay_msec, NULL); |
+ if (ret) |
+ return; |
+ // If we can't set timers, we are in big trouble... but cross our fingers |
+ // for now. |
+ // TODO(jar): If we don't see this error, use a CHECK() here instead. |
+ UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, |
+ MESSAGE_LOOP_PROBLEM_MAX); |
} |
} |