Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: base/message_loop/message_pump_win.cc

Issue 918473002: Process pending delayed tasks in kMsgHaveWork (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/message_loop/message_pump_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/message_loop/message_pump_win.h" 5 #include "base/message_loop/message_pump_win.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <math.h> 8 #include <math.h>
9 9
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/message_loop.h"
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 // We could abort here, but the fear is that this failure mode is plausibly 115 // We could abort here, but the fear is that this failure mode is plausibly
116 // common (queue is full, of about 2000 messages), so we'll do a near-graceful 116 // common (queue is full, of about 2000 messages), so we'll do a near-graceful
117 // recovery. Nested loops are pretty transient (we think), so this will 117 // recovery. Nested loops are pretty transient (we think), so this will
118 // probably be recoverable. 118 // probably be recoverable.
119 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert. 119 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert.
120 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR, 120 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR,
121 MESSAGE_LOOP_PROBLEM_MAX); 121 MESSAGE_LOOP_PROBLEM_MAX);
122 } 122 }
123 123
124 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 124 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
125 //
126 // We would *like* to provide high resolution timers. Windows timers using
127 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup
128 // mechanism because the application can enter modal windows loops where it
129 // is not running our MessageLoop; the only way to have our timers fire in
130 // these cases is to post messages there.
131 //
132 // To provide sub-10ms timers, we process timers directly from our run loop.
133 // For the common case, timers will be processed there as the run loop does
134 // its normal work. However, we *also* set the system timer so that WM_TIMER
135 // events fire. This mops up the case of timers not being able to work in
136 // modal message loops. It is possible for the SetTimer to pop and have no
137 // pending timers, because they could have already been processed by the
138 // run loop itself.
139 //
140 // We use a single SetTimer corresponding to the timer that will expire
141 // soonest. As new timers are created and destroyed, we update SetTimer.
142 // Getting a spurrious SetTimer event firing is benign, as we'll just be
143 // processing an empty timer queue.
144 //
145 delayed_work_time_ = delayed_work_time; 125 delayed_work_time_ = delayed_work_time;
146 126 RescheduleTimer();
147 int delay_msec = GetCurrentDelay();
148 DCHECK_GE(delay_msec, 0);
149 if (delay_msec < USER_TIMER_MINIMUM)
150 delay_msec = USER_TIMER_MINIMUM;
151
152 // Create a WM_TIMER event that will wake us up to check for any pending
153 // timers (in case we are running within a nested, external sub-pump).
154 BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this),
155 delay_msec, NULL);
156 if (ret)
157 return;
158 // If we can't set timers, we are in big trouble... but cross our fingers for
159 // now.
160 // TODO(jar): If we don't see this error, use a CHECK() here instead.
161 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR,
162 MESSAGE_LOOP_PROBLEM_MAX);
163 } 127 }
164 128
165 //----------------------------------------------------------------------------- 129 //-----------------------------------------------------------------------------
166 // MessagePumpForUI private: 130 // MessagePumpForUI private:
167 131
168 // static 132 // static
169 LRESULT CALLBACK MessagePumpForUI::WndProcThunk( 133 LRESULT CALLBACK MessagePumpForUI::WndProcThunk(
170 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { 134 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
171 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. 135 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
172 tracked_objects::ScopedTracker tracking_profile1( 136 tracked_objects::ScopedTracker tracking_profile1(
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 275
312 // Let whatever would have run had we not been putting messages in the queue 276 // Let whatever would have run had we not been putting messages in the queue
313 // run now. This is an attempt to make our dummy message not starve other 277 // run now. This is an attempt to make our dummy message not starve other
314 // messages that may be in the Windows message queue. 278 // messages that may be in the Windows message queue.
315 ProcessPumpReplacementMessage(); 279 ProcessPumpReplacementMessage();
316 280
317 // Now give the delegate a chance to do some work. He'll let us know if he 281 // Now give the delegate a chance to do some work. He'll let us know if he
318 // needs to do more work. 282 // needs to do more work.
319 if (state_->delegate->DoWork()) 283 if (state_->delegate->DoWork())
320 ScheduleWork(); 284 ScheduleWork();
285 state_->delegate->DoDelayedWork(&delayed_work_time_);
286 RescheduleTimer();
321 } 287 }
322 288
323 void MessagePumpForUI::HandleTimerMessage() { 289 void MessagePumpForUI::HandleTimerMessage() {
324 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); 290 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
325 291
326 // If we are being called outside of the context of Run, then don't do 292 // If we are being called outside of the context of Run, then don't do
327 // anything. This could correspond to a MessageBox call or something of 293 // anything. This could correspond to a MessageBox call or something of
328 // that sort. 294 // that sort.
329 if (!state_) 295 if (!state_)
330 return; 296 return;
331 297
332 state_->delegate->DoDelayedWork(&delayed_work_time_); 298 state_->delegate->DoDelayedWork(&delayed_work_time_);
333 if (!delayed_work_time_.is_null()) { 299 RescheduleTimer();
334 // A bit gratuitous to set delayed_work_time_ again, but oh well. 300 }
335 ScheduleDelayedWork(delayed_work_time_); 301
302 void MessagePumpForUI::RescheduleTimer() {
303 if (delayed_work_time_.is_null())
304 return;
305 //
306 // We would *like* to provide high resolution timers. Windows timers using
307 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup
308 // mechanism because the application can enter modal windows loops where it
309 // is not running our MessageLoop; the only way to have our timers fire in
310 // these cases is to post messages there.
311 //
312 // To provide sub-10ms timers, we process timers directly from our run loop.
313 // For the common case, timers will be processed there as the run loop does
314 // its normal work. However, we *also* set the system timer so that WM_TIMER
315 // events fire. This mops up the case of timers not being able to work in
316 // modal message loops. It is possible for the SetTimer to pop and have no
317 // pending timers, because they could have already been processed by the
318 // run loop itself.
319 //
320 // We use a single SetTimer corresponding to the timer that will expire
321 // soonest. As new timers are created and destroyed, we update SetTimer.
322 // Getting a spurrious SetTimer event firing is benign, as we'll just be
323 // processing an empty timer queue.
324 //
325 int delay_msec = GetCurrentDelay();
326 DCHECK_GE(delay_msec, 0);
327 if (delay_msec == 0) {
328 ScheduleWork();
329 } else {
330 if (delay_msec < USER_TIMER_MINIMUM)
331 delay_msec = USER_TIMER_MINIMUM;
332
333 // Create a WM_TIMER event that will wake us up to check for any pending
334 // timers (in case we are running within a nested, external sub-pump).
335 BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this),
336 delay_msec, NULL);
337 if (ret)
338 return;
339 // If we can't set timers, we are in big trouble... but cross our fingers
340 // for now.
341 // TODO(jar): If we don't see this error, use a CHECK() here instead.
342 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR,
343 MESSAGE_LOOP_PROBLEM_MAX);
336 } 344 }
337 } 345 }
338 346
339 bool MessagePumpForUI::ProcessNextWindowsMessage() { 347 bool MessagePumpForUI::ProcessNextWindowsMessage() {
340 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. 348 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
341 tracked_objects::ScopedTracker tracking_profile1( 349 tracked_objects::ScopedTracker tracking_profile1(
342 FROM_HERE_WITH_EXPLICIT_FUNCTION( 350 FROM_HERE_WITH_EXPLICIT_FUNCTION(
343 "440919 MessagePumpForUI::ProcessNextWindowsMessage1")); 351 "440919 MessagePumpForUI::ProcessNextWindowsMessage1"));
344 352
345 // If there are sent messages in the queue then PeekMessage internally 353 // If there are sent messages in the queue then PeekMessage internally
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 698
691 // static 699 // static
692 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( 700 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
693 ULONG_PTR key, 701 ULONG_PTR key,
694 bool* has_valid_io_context) { 702 bool* has_valid_io_context) {
695 *has_valid_io_context = ((key & 1) == 0); 703 *has_valid_io_context = ((key & 1) == 0);
696 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); 704 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
697 } 705 }
698 706
699 } // namespace base 707 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/message_pump_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698