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

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

Issue 1180693002: Update from https://crrev.com/333737 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: rebased Created 5 years, 6 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') | base/metrics/histogram.h » ('j') | 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 11 matching lines...) Expand all
357 "440919 MessagePumpForUI::ProcessNextWindowsMessage2")); 365 "440919 MessagePumpForUI::ProcessNextWindowsMessage2"));
358 366
359 MSG msg; 367 MSG msg;
360 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE) 368 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != FALSE)
361 return ProcessMessageHelper(msg); 369 return ProcessMessageHelper(msg);
362 370
363 return sent_messages_in_queue; 371 return sent_messages_in_queue;
364 } 372 }
365 373
366 bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { 374 bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) {
367 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
368 tracked_objects::ScopedTracker tracking_profile1(
369 FROM_HERE_WITH_EXPLICIT_FUNCTION(
370 "440919 MessagePumpForUI::ProcessMessageHelper1"));
371
372 TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper", 375 TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper",
373 "message", msg.message); 376 "message", msg.message);
374 if (WM_QUIT == msg.message) { 377 if (WM_QUIT == msg.message) {
375 // Repost the QUIT message so that it will be retrieved by the primary 378 // Repost the QUIT message so that it will be retrieved by the primary
376 // GetMessage() loop. 379 // GetMessage() loop.
377 state_->should_quit = true; 380 state_->should_quit = true;
378 PostQuitMessage(static_cast<int>(msg.wParam)); 381 PostQuitMessage(static_cast<int>(msg.wParam));
379 return false; 382 return false;
380 } 383 }
381 384
382 // While running our main message pump, we discard kMsgHaveWork messages. 385 // While running our main message pump, we discard kMsgHaveWork messages.
383 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_) 386 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_)
384 return ProcessPumpReplacementMessage(); 387 return ProcessPumpReplacementMessage();
385 388
386 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
387 tracked_objects::ScopedTracker tracking_profile2(
388 FROM_HERE_WITH_EXPLICIT_FUNCTION(
389 "440919 MessagePumpForUI::ProcessMessageHelper2"));
390
391 if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) 389 if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode))
392 return true; 390 return true;
393 391
394 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
395 tracked_objects::ScopedTracker tracking_profile3(
396 FROM_HERE_WITH_EXPLICIT_FUNCTION(
397 "440919 MessagePumpForUI::ProcessMessageHelper3"));
398
399 uint32_t action = MessagePumpDispatcher::POST_DISPATCH_PERFORM_DEFAULT; 392 uint32_t action = MessagePumpDispatcher::POST_DISPATCH_PERFORM_DEFAULT;
400 if (state_->dispatcher) { 393 if (state_->dispatcher) {
401 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed. 394 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
402 tracked_objects::ScopedTracker tracking_profile4( 395 tracked_objects::ScopedTracker tracking_profile4(
403 FROM_HERE_WITH_EXPLICIT_FUNCTION( 396 FROM_HERE_WITH_EXPLICIT_FUNCTION(
404 "440919 MessagePumpForUI::ProcessMessageHelper4")); 397 "440919 MessagePumpForUI::ProcessMessageHelper4"));
405 398
406 action = state_->dispatcher->Dispatch(msg); 399 action = state_->dispatcher->Dispatch(msg);
407 } 400 }
408 if (action & MessagePumpDispatcher::POST_DISPATCH_QUIT_LOOP) 401 if (action & MessagePumpDispatcher::POST_DISPATCH_QUIT_LOOP)
409 state_->should_quit = true; 402 state_->should_quit = true;
410 if (action & MessagePumpDispatcher::POST_DISPATCH_PERFORM_DEFAULT) { 403 if (action & MessagePumpDispatcher::POST_DISPATCH_PERFORM_DEFAULT) {
411 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
412 tracked_objects::ScopedTracker tracking_profile5(
413 FROM_HERE_WITH_EXPLICIT_FUNCTION(
414 "440919 MessagePumpForUI::ProcessMessageHelper5"));
415
416 TranslateMessage(&msg); 404 TranslateMessage(&msg);
417
418 // TODO(vadimt): Remove ScopedTracker below once crbug.com/440919 is fixed.
419 tracked_objects::ScopedTracker tracking_profile6(
420 FROM_HERE_WITH_EXPLICIT_FUNCTION(
421 "440919 MessagePumpForUI::ProcessMessageHelper6"));
422
423 DispatchMessage(&msg); 405 DispatchMessage(&msg);
424 } 406 }
425 407
426 return true; 408 return true;
427 } 409 }
428 410
429 bool MessagePumpForUI::ProcessPumpReplacementMessage() { 411 bool MessagePumpForUI::ProcessPumpReplacementMessage() {
430 // When we encounter a kMsgHaveWork message, this method is called to peek 412 // When we encounter a kMsgHaveWork message, this method is called to peek
431 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The 413 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The
432 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though 414 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 672
691 // static 673 // static
692 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( 674 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
693 ULONG_PTR key, 675 ULONG_PTR key,
694 bool* has_valid_io_context) { 676 bool* has_valid_io_context) {
695 *has_valid_io_context = ((key & 1) == 0); 677 *has_valid_io_context = ((key & 1) == 0);
696 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); 678 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
697 } 679 }
698 680
699 } // namespace base 681 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/message_pump_win.h ('k') | base/metrics/histogram.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698