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" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/process_util.h" | |
13 #include "base/win/wrapped_window_proc.h" | |
14 | 12 |
15 namespace { | 13 namespace { |
16 | 14 |
17 enum MessageLoopProblems { | 15 enum MessageLoopProblems { |
18 MESSAGE_POST_ERROR, | 16 MESSAGE_POST_ERROR, |
19 COMPLETION_POST_ERROR, | 17 COMPLETION_POST_ERROR, |
20 SET_TIMER_ERROR, | 18 SET_TIMER_ERROR, |
21 MESSAGE_LOOP_PROBLEM_MAX, | 19 MESSAGE_LOOP_PROBLEM_MAX, |
22 }; | 20 }; |
23 | 21 |
24 } // namespace | 22 } // namespace |
25 | 23 |
26 namespace base { | 24 namespace base { |
27 | 25 |
28 static const wchar_t kWndClass[] = L"Chrome_MessagePumpWindow"; | |
29 | |
30 // Message sent to get an additional time slice for pumping (processing) another | 26 // Message sent to get an additional time slice for pumping (processing) another |
31 // task (a series of such messages creates a continuous task pump). | 27 // task (a series of such messages creates a continuous task pump). |
32 static const int kMsgHaveWork = WM_USER + 1; | 28 static const int kMsgHaveWork = WM_USER + 1; |
33 | 29 |
30 // Used by MessagePumpUI to wake up the thread and check any pending timers. | |
31 static const int kTimerId = 1; | |
32 | |
34 //----------------------------------------------------------------------------- | 33 //----------------------------------------------------------------------------- |
35 // MessagePumpWin public: | 34 // MessagePumpWin public: |
36 | 35 |
37 void MessagePumpWin::AddObserver(MessagePumpObserver* observer) { | 36 void MessagePumpWin::AddObserver(MessagePumpObserver* observer) { |
38 observers_.AddObserver(observer); | 37 observers_.AddObserver(observer); |
39 } | 38 } |
40 | 39 |
41 void MessagePumpWin::RemoveObserver(MessagePumpObserver* observer) { | 40 void MessagePumpWin::RemoveObserver(MessagePumpObserver* observer) { |
42 observers_.RemoveObserver(observer); | 41 observers_.RemoveObserver(observer); |
43 } | 42 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 if (delay < 0) | 88 if (delay < 0) |
90 delay = 0; | 89 delay = 0; |
91 | 90 |
92 return delay; | 91 return delay; |
93 } | 92 } |
94 | 93 |
95 //----------------------------------------------------------------------------- | 94 //----------------------------------------------------------------------------- |
96 // MessagePumpForUI public: | 95 // MessagePumpForUI public: |
97 | 96 |
98 MessagePumpForUI::MessagePumpForUI() | 97 MessagePumpForUI::MessagePumpForUI() |
99 : instance_(NULL), | 98 : message_filter_(new MessageFilter), |
100 message_filter_(new MessageFilter) { | 99 window_(new win::MessageWindow()) { |
101 InitMessageWnd(); | 100 CHECK(window_->Create(this)); |
102 } | 101 } |
103 | 102 |
104 MessagePumpForUI::~MessagePumpForUI() { | 103 MessagePumpForUI::~MessagePumpForUI() { |
105 DestroyWindow(message_hwnd_); | |
106 UnregisterClass(kWndClass, instance_); | |
107 } | 104 } |
108 | 105 |
109 void MessagePumpForUI::ScheduleWork() { | 106 void MessagePumpForUI::ScheduleWork() { |
110 if (InterlockedExchange(&have_work_, 1)) | 107 if (InterlockedExchange(&have_work_, 1)) |
111 return; // Someone else continued the pumping. | 108 return; // Someone else continued the pumping. |
112 | 109 |
113 // Make sure the MessagePump does some work for us. | 110 BOOL result = FALSE; |
114 BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork, | 111 |
115 reinterpret_cast<WPARAM>(this), 0); | 112 { |
116 if (ret) | 113 // Take the lock to make sure the window will not be destroyed until |
117 return; // There was room in the Window Message queue. | 114 // PostMessage() returns below. |
115 AutoLock lock(window_lock_); | |
darin (slow to review)
2013/05/25 21:23:17
Is it perhaps worth avoiding this lock when Schedu
alexeypa (please no reviews)
2013/05/29 18:11:52
Just an FYI.
I wrote a test that posts tasks to t
| |
116 if (window_) { | |
117 // Make sure the MessagePump does some work for us. | |
118 if (PostMessage(window_->hwnd(), kMsgHaveWork, 0, 0)) | |
darin (slow to review)
2013/05/24 21:42:58
Perhaps MessageWindow should be reference counted
alexeypa (please no reviews)
2013/05/24 22:22:48
No, the problem is that DestroyWindow() should be
| |
119 return; | |
120 } | |
121 } | |
118 | 122 |
119 // We have failed to insert a have-work message, so there is a chance that we | 123 // We have failed to insert a have-work message, so there is a chance that we |
120 // will starve tasks/timers while sitting in a nested message loop. Nested | 124 // will starve tasks/timers while sitting in a nested message loop. Nested |
121 // loops only look at Windows Message queues, and don't look at *our* task | 125 // loops only look at Windows Message queues, and don't look at *our* task |
122 // queues, etc., so we might not get a time slice in such. :-( | 126 // queues, etc., so we might not get a time slice in such. :-( |
123 // We could abort here, but the fear is that this failure mode is plausibly | 127 // We could abort here, but the fear is that this failure mode is plausibly |
124 // common (queue is full, of about 2000 messages), so we'll do a near-graceful | 128 // common (queue is full, of about 2000 messages), so we'll do a near-graceful |
125 // recovery. Nested loops are pretty transient (we think), so this will | 129 // recovery. Nested loops are pretty transient (we think), so this will |
126 // probably be recoverable. | 130 // probably be recoverable. |
127 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert. | 131 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert. |
128 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR, | 132 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR, |
129 MESSAGE_LOOP_PROBLEM_MAX); | 133 MESSAGE_LOOP_PROBLEM_MAX); |
130 } | 134 } |
131 | 135 |
132 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { | 136 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
137 DCHECK(window_->CalledOnValidThread()); | |
138 | |
133 // | 139 // |
134 // We would *like* to provide high resolution timers. Windows timers using | 140 // We would *like* to provide high resolution timers. Windows timers using |
135 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup | 141 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup |
136 // mechanism because the application can enter modal windows loops where it | 142 // mechanism because the application can enter modal windows loops where it |
137 // is not running our MessageLoop; the only way to have our timers fire in | 143 // is not running our MessageLoop; the only way to have our timers fire in |
138 // these cases is to post messages there. | 144 // these cases is to post messages there. |
139 // | 145 // |
140 // To provide sub-10ms timers, we process timers directly from our run loop. | 146 // To provide sub-10ms timers, we process timers directly from our run loop. |
141 // For the common case, timers will be processed there as the run loop does | 147 // For the common case, timers will be processed there as the run loop does |
142 // its normal work. However, we *also* set the system timer so that WM_TIMER | 148 // its normal work. However, we *also* set the system timer so that WM_TIMER |
143 // events fire. This mops up the case of timers not being able to work in | 149 // events fire. This mops up the case of timers not being able to work in |
144 // modal message loops. It is possible for the SetTimer to pop and have no | 150 // modal message loops. It is possible for the SetTimer to pop and have no |
145 // pending timers, because they could have already been processed by the | 151 // pending timers, because they could have already been processed by the |
146 // run loop itself. | 152 // run loop itself. |
147 // | 153 // |
148 // We use a single SetTimer corresponding to the timer that will expire | 154 // We use a single SetTimer corresponding to the timer that will expire |
149 // soonest. As new timers are created and destroyed, we update SetTimer. | 155 // soonest. As new timers are created and destroyed, we update SetTimer. |
150 // Getting a spurrious SetTimer event firing is benign, as we'll just be | 156 // Getting a spurrious SetTimer event firing is benign, as we'll just be |
151 // processing an empty timer queue. | 157 // processing an empty timer queue. |
152 // | 158 // |
153 delayed_work_time_ = delayed_work_time; | 159 delayed_work_time_ = delayed_work_time; |
154 | 160 |
155 int delay_msec = GetCurrentDelay(); | 161 int delay_msec = GetCurrentDelay(); |
156 DCHECK_GE(delay_msec, 0); | 162 DCHECK_GE(delay_msec, 0); |
157 if (delay_msec < USER_TIMER_MINIMUM) | 163 if (delay_msec < USER_TIMER_MINIMUM) |
158 delay_msec = USER_TIMER_MINIMUM; | 164 delay_msec = USER_TIMER_MINIMUM; |
159 | 165 |
160 // Create a WM_TIMER event that will wake us up to check for any pending | 166 // Create a WM_TIMER event that will wake us up to check for any pending |
161 // timers (in case we are running within a nested, external sub-pump). | 167 // timers (in case we are running within a nested, external sub-pump). |
162 BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), | 168 BOOL ret = SetTimer(window_->hwnd(), kTimerId, delay_msec, NULL); |
163 delay_msec, NULL); | |
164 if (ret) | 169 if (ret) |
165 return; | 170 return; |
166 // If we can't set timers, we are in big trouble... but cross our fingers for | 171 // If we can't set timers, we are in big trouble... but cross our fingers for |
167 // now. | 172 // now. |
168 // TODO(jar): If we don't see this error, use a CHECK() here instead. | 173 // TODO(jar): If we don't see this error, use a CHECK() here instead. |
169 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, | 174 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, |
170 MESSAGE_LOOP_PROBLEM_MAX); | 175 MESSAGE_LOOP_PROBLEM_MAX); |
171 } | 176 } |
172 | 177 |
178 void MessagePumpForUI::WillDestroyCurrentMessageLoop() { | |
179 DCHECK(window_->CalledOnValidThread()); | |
180 | |
181 // Synchronize with MessagePumpForUI::ScheduleWork() that can access |window_| | |
182 // on arbitrary thread. | |
183 AutoLock lock(window_lock_); | |
184 window_.reset(); | |
185 } | |
186 | |
173 void MessagePumpForUI::PumpOutPendingPaintMessages() { | 187 void MessagePumpForUI::PumpOutPendingPaintMessages() { |
174 // If we are being called outside of the context of Run, then don't try to do | 188 // If we are being called outside of the context of Run, then don't try to do |
175 // any work. | 189 // any work. |
176 if (!state_) | 190 if (!state_) |
177 return; | 191 return; |
178 | 192 |
179 // Create a mini-message-pump to force immediate processing of only Windows | 193 // Create a mini-message-pump to force immediate processing of only Windows |
180 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking | 194 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking |
181 // to get the job done. Actual common max is 4 peeks, but we'll be a little | 195 // to get the job done. Actual common max is 4 peeks, but we'll be a little |
182 // safe here. | 196 // safe here. |
183 const int kMaxPeekCount = 20; | 197 const int kMaxPeekCount = 20; |
184 int peek_count; | 198 int peek_count; |
185 for (peek_count = 0; peek_count < kMaxPeekCount; ++peek_count) { | 199 for (peek_count = 0; peek_count < kMaxPeekCount; ++peek_count) { |
186 MSG msg; | 200 MSG msg; |
187 if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_PAINT)) | 201 if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_PAINT)) |
188 break; | 202 break; |
189 ProcessMessageHelper(msg); | 203 ProcessMessageHelper(msg); |
190 if (state_->should_quit) // Handle WM_QUIT. | 204 if (state_->should_quit) // Handle WM_QUIT. |
191 break; | 205 break; |
192 } | 206 } |
193 // Histogram what was really being used, to help to adjust kMaxPeekCount. | 207 // Histogram what was really being used, to help to adjust kMaxPeekCount. |
194 DHISTOGRAM_COUNTS("Loop.PumpOutPendingPaintMessages Peeks", peek_count); | 208 DHISTOGRAM_COUNTS("Loop.PumpOutPendingPaintMessages Peeks", peek_count); |
195 } | 209 } |
196 | 210 |
197 //----------------------------------------------------------------------------- | 211 //----------------------------------------------------------------------------- |
198 // MessagePumpForUI private: | 212 // MessagePumpForUI private: |
199 | 213 |
200 // static | 214 bool MessagePumpForUI::HandleMessage(HWND hwnd, |
201 LRESULT CALLBACK MessagePumpForUI::WndProcThunk( | 215 UINT message, |
202 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { | 216 WPARAM wparam, |
217 LPARAM lparam, | |
218 LRESULT* result) { | |
203 switch (message) { | 219 switch (message) { |
204 case kMsgHaveWork: | 220 case kMsgHaveWork: |
205 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage(); | 221 HandleWorkMessage(); |
206 break; | 222 break; |
223 | |
207 case WM_TIMER: | 224 case WM_TIMER: |
208 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage(); | 225 HandleTimerMessage(); |
209 break; | 226 break; |
210 } | 227 } |
211 return DefWindowProc(hwnd, message, wparam, lparam); | 228 |
229 // Do default processing for all messages. | |
230 return false; | |
212 } | 231 } |
213 | 232 |
214 void MessagePumpForUI::DoRunLoop() { | 233 void MessagePumpForUI::DoRunLoop() { |
234 DCHECK(window_->CalledOnValidThread()); | |
235 | |
215 // IF this was just a simple PeekMessage() loop (servicing all possible work | 236 // IF this was just a simple PeekMessage() loop (servicing all possible work |
216 // queues), then Windows would try to achieve the following order according | 237 // queues), then Windows would try to achieve the following order according |
217 // to MSDN documentation about PeekMessage with no filter): | 238 // to MSDN documentation about PeekMessage with no filter): |
218 // * Sent messages | 239 // * Sent messages |
219 // * Posted messages | 240 // * Posted messages |
220 // * Sent messages (again) | 241 // * Sent messages (again) |
221 // * WM_PAINT messages | 242 // * WM_PAINT messages |
222 // * WM_TIMER messages | 243 // * WM_TIMER messages |
223 // | 244 // |
224 // Summary: none of the above classes is starved, and sent messages has twice | 245 // Summary: none of the above classes is starved, and sent messages has twice |
(...skipping 17 matching lines...) Expand all Loading... | |
242 if (state_->should_quit) | 263 if (state_->should_quit) |
243 break; | 264 break; |
244 | 265 |
245 more_work_is_plausible |= | 266 more_work_is_plausible |= |
246 state_->delegate->DoDelayedWork(&delayed_work_time_); | 267 state_->delegate->DoDelayedWork(&delayed_work_time_); |
247 // If we did not process any delayed work, then we can assume that our | 268 // If we did not process any delayed work, then we can assume that our |
248 // existing WM_TIMER if any will fire when delayed work should run. We | 269 // existing WM_TIMER if any will fire when delayed work should run. We |
249 // don't want to disturb that timer if it is already in flight. However, | 270 // don't want to disturb that timer if it is already in flight. However, |
250 // if we did do all remaining delayed work, then lets kill the WM_TIMER. | 271 // if we did do all remaining delayed work, then lets kill the WM_TIMER. |
251 if (more_work_is_plausible && delayed_work_time_.is_null()) | 272 if (more_work_is_plausible && delayed_work_time_.is_null()) |
252 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); | 273 KillTimer(window_->hwnd(), kTimerId); |
253 if (state_->should_quit) | 274 if (state_->should_quit) |
254 break; | 275 break; |
255 | 276 |
256 if (more_work_is_plausible) | 277 if (more_work_is_plausible) |
257 continue; | 278 continue; |
258 | 279 |
259 more_work_is_plausible = state_->delegate->DoIdleWork(); | 280 more_work_is_plausible = state_->delegate->DoIdleWork(); |
260 if (state_->should_quit) | 281 if (state_->should_quit) |
261 break; | 282 break; |
262 | 283 |
263 if (more_work_is_plausible) | 284 if (more_work_is_plausible) |
264 continue; | 285 continue; |
265 | 286 |
266 WaitForWork(); // Wait (sleep) until we have work to do again. | 287 WaitForWork(); // Wait (sleep) until we have work to do again. |
267 } | 288 } |
268 } | 289 } |
269 | 290 |
270 void MessagePumpForUI::InitMessageWnd() { | |
271 WNDCLASSEX wc = {0}; | |
272 wc.cbSize = sizeof(wc); | |
273 wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>; | |
274 wc.hInstance = base::GetModuleFromAddress(wc.lpfnWndProc); | |
275 wc.lpszClassName = kWndClass; | |
276 instance_ = wc.hInstance; | |
277 RegisterClassEx(&wc); | |
278 | |
279 message_hwnd_ = | |
280 CreateWindow(kWndClass, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, instance_, 0); | |
281 DCHECK(message_hwnd_); | |
282 } | |
283 | |
284 void MessagePumpForUI::WaitForWork() { | 291 void MessagePumpForUI::WaitForWork() { |
285 // Wait until a message is available, up to the time needed by the timer | 292 // Wait until a message is available, up to the time needed by the timer |
286 // manager to fire the next set of timers. | 293 // manager to fire the next set of timers. |
287 int delay = GetCurrentDelay(); | 294 int delay = GetCurrentDelay(); |
288 if (delay < 0) // Negative value means no timers waiting. | 295 if (delay < 0) // Negative value means no timers waiting. |
289 delay = INFINITE; | 296 delay = INFINITE; |
290 | 297 |
291 DWORD result; | 298 DWORD result; |
292 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT, | 299 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT, |
293 MWMO_INPUTAVAILABLE); | 300 MWMO_INPUTAVAILABLE); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
331 // messages that may be in the Windows message queue. | 338 // messages that may be in the Windows message queue. |
332 ProcessPumpReplacementMessage(); | 339 ProcessPumpReplacementMessage(); |
333 | 340 |
334 // Now give the delegate a chance to do some work. He'll let us know if he | 341 // Now give the delegate a chance to do some work. He'll let us know if he |
335 // needs to do more work. | 342 // needs to do more work. |
336 if (state_->delegate->DoWork()) | 343 if (state_->delegate->DoWork()) |
337 ScheduleWork(); | 344 ScheduleWork(); |
338 } | 345 } |
339 | 346 |
340 void MessagePumpForUI::HandleTimerMessage() { | 347 void MessagePumpForUI::HandleTimerMessage() { |
341 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); | 348 KillTimer(window_->hwnd(), kTimerId); |
342 | 349 |
343 // If we are being called outside of the context of Run, then don't do | 350 // If we are being called outside of the context of Run, then don't do |
344 // anything. This could correspond to a MessageBox call or something of | 351 // anything. This could correspond to a MessageBox call or something of |
345 // that sort. | 352 // that sort. |
346 if (!state_) | 353 if (!state_) |
347 return; | 354 return; |
348 | 355 |
349 state_->delegate->DoDelayedWork(&delayed_work_time_); | 356 state_->delegate->DoDelayedWork(&delayed_work_time_); |
350 if (!delayed_work_time_.is_null()) { | 357 if (!delayed_work_time_.is_null()) { |
351 // A bit gratuitous to set delayed_work_time_ again, but oh well. | 358 // A bit gratuitous to set delayed_work_time_ again, but oh well. |
(...skipping 23 matching lines...) Expand all Loading... | |
375 "message", msg.message); | 382 "message", msg.message); |
376 if (WM_QUIT == msg.message) { | 383 if (WM_QUIT == msg.message) { |
377 // Repost the QUIT message so that it will be retrieved by the primary | 384 // Repost the QUIT message so that it will be retrieved by the primary |
378 // GetMessage() loop. | 385 // GetMessage() loop. |
379 state_->should_quit = true; | 386 state_->should_quit = true; |
380 PostQuitMessage(static_cast<int>(msg.wParam)); | 387 PostQuitMessage(static_cast<int>(msg.wParam)); |
381 return false; | 388 return false; |
382 } | 389 } |
383 | 390 |
384 // While running our main message pump, we discard kMsgHaveWork messages. | 391 // While running our main message pump, we discard kMsgHaveWork messages. |
385 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_) | 392 if (msg.message == kMsgHaveWork && msg.hwnd == window_->hwnd()) |
386 return ProcessPumpReplacementMessage(); | 393 return ProcessPumpReplacementMessage(); |
387 | 394 |
388 if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) | 395 if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) |
389 return true; | 396 return true; |
390 | 397 |
391 WillProcessMessage(msg); | 398 WillProcessMessage(msg); |
392 | 399 |
393 if (!message_filter_->ProcessMessage(msg)) { | 400 if (!message_filter_->ProcessMessage(msg)) { |
394 if (state_->dispatcher) { | 401 if (state_->dispatcher) { |
395 if (!state_->dispatcher->Dispatch(msg)) | 402 if (!state_->dispatcher->Dispatch(msg)) |
(...skipping 26 matching lines...) Expand all Loading... | |
422 if (MessageLoop::current()->os_modal_loop()) { | 429 if (MessageLoop::current()->os_modal_loop()) { |
423 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above. | 430 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above. |
424 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || | 431 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || |
425 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE); | 432 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE); |
426 } else { | 433 } else { |
427 have_message = !!message_filter_->DoPeekMessage(&msg, NULL, 0, 0, | 434 have_message = !!message_filter_->DoPeekMessage(&msg, NULL, 0, 0, |
428 PM_REMOVE); | 435 PM_REMOVE); |
429 } | 436 } |
430 | 437 |
431 DCHECK(!have_message || kMsgHaveWork != msg.message || | 438 DCHECK(!have_message || kMsgHaveWork != msg.message || |
432 msg.hwnd != message_hwnd_); | 439 msg.hwnd != window_->hwnd()); |
433 | 440 |
434 // Since we discarded a kMsgHaveWork message, we must update the flag. | 441 // Since we discarded a kMsgHaveWork message, we must update the flag. |
435 int old_have_work = InterlockedExchange(&have_work_, 0); | 442 int old_have_work = InterlockedExchange(&have_work_, 0); |
436 DCHECK(old_have_work); | 443 DCHECK(old_have_work); |
437 | 444 |
438 // We don't need a special time slice if we didn't have_message to process. | 445 // We don't need a special time slice if we didn't have_message to process. |
439 if (!have_message) | 446 if (!have_message) |
440 return false; | 447 return false; |
441 | 448 |
442 // Guarantee we'll get another time slice in the case where we go into native | 449 // Guarantee we'll get another time slice in the case where we go into native |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
671 | 678 |
672 // static | 679 // static |
673 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( | 680 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( |
674 ULONG_PTR key, | 681 ULONG_PTR key, |
675 bool* has_valid_io_context) { | 682 bool* has_valid_io_context) { |
676 *has_valid_io_context = ((key & 1) == 0); | 683 *has_valid_io_context = ((key & 1) == 0); |
677 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); | 684 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); |
678 } | 685 } |
679 | 686 |
680 } // namespace base | 687 } // namespace base |
OLD | NEW |