Chromium Code Reviews| OLD | NEW |
|---|---|
| 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_pump_win.h" | 5 #include "base/message_pump_win.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 60 s.run_depth = state_ ? state_->run_depth + 1 : 1; | 60 s.run_depth = state_ ? state_->run_depth + 1 : 1; |
| 61 | 61 |
| 62 RunState* previous_state = state_; | 62 RunState* previous_state = state_; |
| 63 state_ = &s; | 63 state_ = &s; |
| 64 | 64 |
| 65 DoRunLoop(); | 65 DoRunLoop(); |
| 66 | 66 |
| 67 state_ = previous_state; | 67 state_ = previous_state; |
| 68 } | 68 } |
| 69 | 69 |
| 70 void MessagePumpWin::Run(Delegate* delegate) { | |
| 71 RunWithDispatcher(delegate, NULL); | |
| 72 } | |
| 73 | |
| 70 void MessagePumpWin::Quit() { | 74 void MessagePumpWin::Quit() { |
| 71 DCHECK(state_); | 75 DCHECK(state_); |
| 72 state_->should_quit = true; | 76 state_->should_quit = true; |
| 73 } | 77 } |
| 74 | 78 |
| 75 //----------------------------------------------------------------------------- | 79 //----------------------------------------------------------------------------- |
| 76 // MessagePumpWin protected: | 80 // MessagePumpWin protected: |
| 77 | 81 |
| 78 int MessagePumpWin::GetCurrentDelay() const { | 82 int MessagePumpWin::GetCurrentDelay() const { |
| 79 if (delayed_work_time_.is_null()) | 83 if (delayed_work_time_.is_null()) |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 96 //----------------------------------------------------------------------------- | 100 //----------------------------------------------------------------------------- |
| 97 // MessagePumpForUI public: | 101 // MessagePumpForUI public: |
| 98 | 102 |
| 99 MessagePumpForUI::MessagePumpForUI() | 103 MessagePumpForUI::MessagePumpForUI() |
| 100 : atom_(0), | 104 : atom_(0), |
| 101 message_filter_(new MessageFilter) { | 105 message_filter_(new MessageFilter) { |
| 102 InitMessageWnd(); | 106 InitMessageWnd(); |
| 103 } | 107 } |
| 104 | 108 |
| 105 MessagePumpForUI::~MessagePumpForUI() { | 109 MessagePumpForUI::~MessagePumpForUI() { |
| 106 DestroyWindow(message_hwnd_); | 110 DCHECK(!atom_); |
| 107 UnregisterClass(MAKEINTATOM(atom_), | 111 DCHECK(!message_hwnd_); |
| 108 base::GetModuleFromAddress(&WndProcThunk)); | |
| 109 } | 112 } |
| 110 | 113 |
| 111 void MessagePumpForUI::ScheduleWork() { | 114 void MessagePumpForUI::ScheduleWork() { |
| 112 if (InterlockedExchange(&have_work_, 1)) | 115 if (InterlockedExchange(&have_work_, 1)) |
| 113 return; // Someone else continued the pumping. | 116 return; // Someone else continued the pumping. |
| 114 | 117 |
| 115 // Make sure the MessagePump does some work for us. | 118 { |
| 116 BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork, | 119 base::AutoLock lock(message_hwnd_lock_); |
|
rvargas (doing something else)
2013/06/12 23:03:22
doing:
if (!message_hwnd_lock_.Try())
return;
M
alexeypa (please no reviews)
2013/06/13 00:13:40
Done.
| |
| 117 reinterpret_cast<WPARAM>(this), 0); | 120 |
| 118 if (ret) | 121 // Do nothing if the window has been destoryed already. There is no thread |
|
rvargas (doing something else)
2013/06/12 23:03:22
nit: remove the last sentence... there may be a th
alexeypa (please no reviews)
2013/06/13 00:13:40
Done.
| |
| 119 return; // There was room in the Window Message queue. | 122 // to wake up at this point. |
| 123 if (!message_hwnd_) | |
| 124 return; | |
| 125 | |
| 126 // Make sure the MessagePump does some work for us. | |
| 127 if (PostMessage(message_hwnd_, kMsgHaveWork, | |
| 128 reinterpret_cast<WPARAM>(this), 0)) { | |
| 129 return; | |
| 130 } | |
| 131 } | |
| 120 | 132 |
| 121 // We have failed to insert a have-work message, so there is a chance that we | 133 // We have failed to insert a have-work message, so there is a chance that we |
| 122 // will starve tasks/timers while sitting in a nested message loop. Nested | 134 // will starve tasks/timers while sitting in a nested message loop. Nested |
| 123 // loops only look at Windows Message queues, and don't look at *our* task | 135 // loops only look at Windows Message queues, and don't look at *our* task |
| 124 // queues, etc., so we might not get a time slice in such. :-( | 136 // queues, etc., so we might not get a time slice in such. :-( |
| 125 // We could abort here, but the fear is that this failure mode is plausibly | 137 // We could abort here, but the fear is that this failure mode is plausibly |
| 126 // common (queue is full, of about 2000 messages), so we'll do a near-graceful | 138 // common (queue is full, of about 2000 messages), so we'll do a near-graceful |
| 127 // recovery. Nested loops are pretty transient (we think), so this will | 139 // recovery. Nested loops are pretty transient (we think), so this will |
| 128 // probably be recoverable. | 140 // probably be recoverable. |
| 129 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert. | 141 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 delay_msec, NULL); | 177 delay_msec, NULL); |
| 166 if (ret) | 178 if (ret) |
| 167 return; | 179 return; |
| 168 // If we can't set timers, we are in big trouble... but cross our fingers for | 180 // If we can't set timers, we are in big trouble... but cross our fingers for |
| 169 // now. | 181 // now. |
| 170 // TODO(jar): If we don't see this error, use a CHECK() here instead. | 182 // TODO(jar): If we don't see this error, use a CHECK() here instead. |
| 171 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, | 183 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, |
| 172 MESSAGE_LOOP_PROBLEM_MAX); | 184 MESSAGE_LOOP_PROBLEM_MAX); |
| 173 } | 185 } |
| 174 | 186 |
| 187 void MessagePumpForUI::Stop() { | |
| 188 HWND message_hwnd; | |
| 189 { | |
| 190 base::AutoLock lock(message_hwnd_lock_); | |
| 191 | |
| 192 // Let ScheduleWork() know that the window has been destoyed. | |
| 193 message_hwnd = message_hwnd_; | |
| 194 message_hwnd_ = NULL; | |
| 195 } | |
| 196 | |
| 197 // Destoy the window and its class. The destructor checks whether | |
| 198 // |message_hwnd_| and |atom_| are destroyed, so the variables should be | |
| 199 // cleared here. | |
| 200 DestroyWindow(message_hwnd); | |
| 201 UnregisterClass(MAKEINTATOM(atom_), | |
| 202 base::GetModuleFromAddress(&WndProcThunk)); | |
| 203 atom_ = 0; | |
| 204 } | |
| 205 | |
| 175 void MessagePumpForUI::PumpOutPendingPaintMessages() { | 206 void MessagePumpForUI::PumpOutPendingPaintMessages() { |
| 176 // If we are being called outside of the context of Run, then don't try to do | 207 // If we are being called outside of the context of Run, then don't try to do |
| 177 // any work. | 208 // any work. |
| 178 if (!state_) | 209 if (!state_) |
| 179 return; | 210 return; |
| 180 | 211 |
| 181 // Create a mini-message-pump to force immediate processing of only Windows | 212 // Create a mini-message-pump to force immediate processing of only Windows |
| 182 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking | 213 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking |
| 183 // to get the job done. Actual common max is 4 peeks, but we'll be a little | 214 // to get the job done. Actual common max is 4 peeks, but we'll be a little |
| 184 // safe here. | 215 // safe here. |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 471 return; // Someone else continued the pumping. | 502 return; // Someone else continued the pumping. |
| 472 | 503 |
| 473 // Make sure the MessagePump does some work for us. | 504 // Make sure the MessagePump does some work for us. |
| 474 BOOL ret = PostQueuedCompletionStatus(port_, 0, | 505 BOOL ret = PostQueuedCompletionStatus(port_, 0, |
| 475 reinterpret_cast<ULONG_PTR>(this), | 506 reinterpret_cast<ULONG_PTR>(this), |
| 476 reinterpret_cast<OVERLAPPED*>(this)); | 507 reinterpret_cast<OVERLAPPED*>(this)); |
| 477 if (ret) | 508 if (ret) |
| 478 return; // Post worked perfectly. | 509 return; // Post worked perfectly. |
| 479 | 510 |
| 480 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery. | 511 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery. |
| 481 InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed. | 512 InterlockedExchange(&have_work_, 0); |
| 482 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR, | 513 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR, |
| 483 MESSAGE_LOOP_PROBLEM_MAX); | 514 MESSAGE_LOOP_PROBLEM_MAX); |
| 484 } | 515 } |
| 485 | 516 |
| 486 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { | 517 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
| 487 // We know that we can't be blocked right now since this method can only be | 518 // We know that we can't be blocked right now since this method can only be |
| 488 // called on the same thread as Run, so we only need to update our record of | 519 // called on the same thread as Run, so we only need to update our record of |
| 489 // how long to sleep when we do sleep. | 520 // how long to sleep when we do sleep. |
| 490 delayed_work_time_ = delayed_work_time; | 521 delayed_work_time_ = delayed_work_time; |
| 491 } | 522 } |
| 492 | 523 |
| 524 void MessagePumpForIO::Stop() { | |
| 525 } | |
| 526 | |
| 493 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, | 527 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, |
| 494 IOHandler* handler) { | 528 IOHandler* handler) { |
| 495 ULONG_PTR key = HandlerToKey(handler, true); | 529 ULONG_PTR key = HandlerToKey(handler, true); |
| 496 HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1); | 530 HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1); |
| 497 DPCHECK(port); | 531 DPCHECK(port); |
| 498 } | 532 } |
| 499 | 533 |
| 500 bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle, | 534 bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle, |
| 501 IOHandler* handler) { | 535 IOHandler* handler) { |
| 502 // Job object notifications use the OVERLAPPED pointer to carry the message | 536 // Job object notifications use the OVERLAPPED pointer to carry the message |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 677 | 711 |
| 678 // static | 712 // static |
| 679 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( | 713 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( |
| 680 ULONG_PTR key, | 714 ULONG_PTR key, |
| 681 bool* has_valid_io_context) { | 715 bool* has_valid_io_context) { |
| 682 *has_valid_io_context = ((key & 1) == 0); | 716 *has_valid_io_context = ((key & 1) == 0); |
| 683 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); | 717 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); |
| 684 } | 718 } |
| 685 | 719 |
| 686 } // namespace base | 720 } // namespace base |
| OLD | NEW |