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

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

Issue 2457393005: Remove USER32 Function Pointer Loading from MessagePumpWin (Closed)
Patch Set: Created 4 years, 1 month 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 | « no previous file | 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 <math.h> 7 #include <math.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <limits> 10 #include <limits>
(...skipping 11 matching lines...) Expand all
22 namespace { 22 namespace {
23 23
24 enum MessageLoopProblems { 24 enum MessageLoopProblems {
25 MESSAGE_POST_ERROR, 25 MESSAGE_POST_ERROR,
26 COMPLETION_POST_ERROR, 26 COMPLETION_POST_ERROR,
27 SET_TIMER_ERROR, 27 SET_TIMER_ERROR,
28 RECEIVED_WM_QUIT_ERROR, 28 RECEIVED_WM_QUIT_ERROR,
29 MESSAGE_LOOP_PROBLEM_MAX, 29 MESSAGE_LOOP_PROBLEM_MAX,
30 }; 30 };
31 31
32 // The following define pointers to user32 API's for the API's which are used
33 // in this file. These are added to avoid directly depending on user32 from
34 // base as there are users of base who don't want this.
35 decltype(::TranslateMessage)* g_translate_message = nullptr;
36 decltype(::DispatchMessageW)* g_dispatch_message = nullptr;
37 decltype(::PeekMessageW)* g_peek_message = nullptr;
38 decltype(::PostMessageW)* g_post_message = nullptr;
39 decltype(::DefWindowProcW)* g_def_window_proc = nullptr;
40 decltype(::PostQuitMessage)* g_post_quit = nullptr;
41 decltype(::UnregisterClassW)* g_unregister_class = nullptr;
42 decltype(::RegisterClassExW)* g_register_class = nullptr;
43 decltype(::CreateWindowExW)* g_create_window_ex = nullptr;
44 decltype(::DestroyWindow)* g_destroy_window = nullptr;
45 decltype(::CallMsgFilterW)* g_call_msg_filter = nullptr;
46 decltype(::GetQueueStatus)* g_get_queue_status = nullptr;
47 decltype(::MsgWaitForMultipleObjectsEx)* g_msg_wait_for_multiple_objects_ex =
48 nullptr;
49 decltype(::SetTimer)* g_set_timer = nullptr;
50 decltype(::KillTimer)* g_kill_timer = nullptr;
51
52 #define GET_USER32_API(module, name) \
53 reinterpret_cast<decltype(name)*>(::GetProcAddress(module, #name))
54
55 // Initializes the global pointers to user32 APIs for the API's used in this
56 // file.
57 void InitUser32APIs() {
58 if (g_translate_message)
59 return;
60
61 HMODULE user32_module = ::GetModuleHandle(L"user32.dll");
62 CHECK(user32_module);
63
64 g_translate_message = GET_USER32_API(user32_module, TranslateMessage);
65 CHECK(g_translate_message);
66
67 g_dispatch_message = GET_USER32_API(user32_module, DispatchMessageW);
68 CHECK(g_dispatch_message);
69
70 g_peek_message = GET_USER32_API(user32_module, PeekMessageW);
71 CHECK(g_peek_message);
72
73 g_post_message = GET_USER32_API(user32_module, PostMessageW);
74 CHECK(g_post_message);
75
76 g_def_window_proc = GET_USER32_API(user32_module, DefWindowProcW);
77 CHECK(g_def_window_proc);
78
79 g_post_quit = GET_USER32_API(user32_module, PostQuitMessage);
80 CHECK(g_post_quit);
81
82 g_unregister_class = GET_USER32_API(user32_module, UnregisterClassW);
83 CHECK(g_unregister_class);
84
85 g_register_class = GET_USER32_API(user32_module, RegisterClassExW);
86 CHECK(g_register_class);
87
88 g_create_window_ex = GET_USER32_API(user32_module, CreateWindowExW);
89 CHECK(g_create_window_ex);
90
91 g_destroy_window = GET_USER32_API(user32_module, DestroyWindow);
92 CHECK(g_destroy_window);
93
94 g_call_msg_filter = GET_USER32_API(user32_module, CallMsgFilterW);
95 CHECK(g_call_msg_filter);
96
97 g_get_queue_status = GET_USER32_API(user32_module, GetQueueStatus);
98 CHECK(g_get_queue_status);
99
100 g_msg_wait_for_multiple_objects_ex =
101 GET_USER32_API(user32_module, MsgWaitForMultipleObjectsEx);
102 CHECK(g_msg_wait_for_multiple_objects_ex);
103
104 g_set_timer = GET_USER32_API(user32_module, SetTimer);
105 CHECK(g_set_timer);
106
107 g_kill_timer = GET_USER32_API(user32_module, KillTimer);
108 CHECK(g_kill_timer);
109 }
110
111 } // namespace 32 } // namespace
112 33
113 static const wchar_t kWndClassFormat[] = L"Chrome_MessagePumpWindow_%p"; 34 static const wchar_t kWndClassFormat[] = L"Chrome_MessagePumpWindow_%p";
114 35
115 // Message sent to get an additional time slice for pumping (processing) another 36 // Message sent to get an additional time slice for pumping (processing) another
116 // task (a series of such messages creates a continuous task pump). 37 // task (a series of such messages creates a continuous task pump).
117 static const int kMsgHaveWork = WM_USER + 1; 38 static const int kMsgHaveWork = WM_USER + 1;
118 39
119 // The application-defined code passed to the hook procedure. 40 // The application-defined code passed to the hook procedure.
120 static const int kMessageFilterCode = 0x5001; 41 static const int kMessageFilterCode = 0x5001;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 return timeout < 0 ? 0 : 89 return timeout < 0 ? 0 :
169 (timeout > std::numeric_limits<int>::max() ? 90 (timeout > std::numeric_limits<int>::max() ?
170 std::numeric_limits<int>::max() : static_cast<int>(timeout)); 91 std::numeric_limits<int>::max() : static_cast<int>(timeout));
171 } 92 }
172 93
173 //----------------------------------------------------------------------------- 94 //-----------------------------------------------------------------------------
174 // MessagePumpForUI public: 95 // MessagePumpForUI public:
175 96
176 MessagePumpForUI::MessagePumpForUI() 97 MessagePumpForUI::MessagePumpForUI()
177 : atom_(0) { 98 : atom_(0) {
178 InitUser32APIs();
179 InitMessageWnd(); 99 InitMessageWnd();
180 } 100 }
181 101
182 MessagePumpForUI::~MessagePumpForUI() { 102 MessagePumpForUI::~MessagePumpForUI() {
183 g_destroy_window(message_hwnd_); 103 DestroyWindow(message_hwnd_);
184 g_unregister_class(MAKEINTATOM(atom_), CURRENT_MODULE()); 104 UnregisterClass(MAKEINTATOM(atom_), CURRENT_MODULE());
185 } 105 }
186 106
187 void MessagePumpForUI::ScheduleWork() { 107 void MessagePumpForUI::ScheduleWork() {
188 if (InterlockedExchange(&work_state_, HAVE_WORK) != READY) 108 if (InterlockedExchange(&work_state_, HAVE_WORK) != READY)
189 return; // Someone else continued the pumping. 109 return; // Someone else continued the pumping.
190 110
191 // Make sure the MessagePump does some work for us. 111 // Make sure the MessagePump does some work for us.
192 BOOL ret = g_post_message(message_hwnd_, kMsgHaveWork, 112 BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork,
193 reinterpret_cast<WPARAM>(this), 0); 113 reinterpret_cast<WPARAM>(this), 0);
194 if (ret) 114 if (ret)
195 return; // There was room in the Window Message queue. 115 return; // There was room in the Window Message queue.
196 116
197 // We have failed to insert a have-work message, so there is a chance that we 117 // We have failed to insert a have-work message, so there is a chance that we
198 // will starve tasks/timers while sitting in a nested message loop. Nested 118 // will starve tasks/timers while sitting in a nested message loop. Nested
199 // loops only look at Windows Message queues, and don't look at *our* task 119 // loops only look at Windows Message queues, and don't look at *our* task
200 // queues, etc., so we might not get a time slice in such. :-( 120 // queues, etc., so we might not get a time slice in such. :-(
201 // We could abort here, but the fear is that this failure mode is plausibly 121 // We could abort here, but the fear is that this failure mode is plausibly
202 // common (queue is full, of about 2000 messages), so we'll do a near-graceful 122 // common (queue is full, of about 2000 messages), so we'll do a near-graceful
203 // recovery. Nested loops are pretty transient (we think), so this will 123 // recovery. Nested loops are pretty transient (we think), so this will
(...skipping 19 matching lines...) Expand all
223 LRESULT CALLBACK MessagePumpForUI::WndProcThunk( 143 LRESULT CALLBACK MessagePumpForUI::WndProcThunk(
224 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { 144 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
225 switch (message) { 145 switch (message) {
226 case kMsgHaveWork: 146 case kMsgHaveWork:
227 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage(); 147 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage();
228 break; 148 break;
229 case WM_TIMER: 149 case WM_TIMER:
230 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage(); 150 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage();
231 break; 151 break;
232 } 152 }
233 return g_def_window_proc(hwnd, message, wparam, lparam); 153 return DefWindowProc(hwnd, message, wparam, lparam);
234 } 154 }
235 155
236 void MessagePumpForUI::DoRunLoop() { 156 void MessagePumpForUI::DoRunLoop() {
237 // IF this was just a simple PeekMessage() loop (servicing all possible work 157 // IF this was just a simple PeekMessage() loop (servicing all possible work
238 // queues), then Windows would try to achieve the following order according 158 // queues), then Windows would try to achieve the following order according
239 // to MSDN documentation about PeekMessage with no filter): 159 // to MSDN documentation about PeekMessage with no filter):
240 // * Sent messages 160 // * Sent messages
241 // * Posted messages 161 // * Posted messages
242 // * Sent messages (again) 162 // * Sent messages (again)
243 // * WM_PAINT messages 163 // * WM_PAINT messages
(...skipping 20 matching lines...) Expand all
264 if (state_->should_quit) 184 if (state_->should_quit)
265 break; 185 break;
266 186
267 more_work_is_plausible |= 187 more_work_is_plausible |=
268 state_->delegate->DoDelayedWork(&delayed_work_time_); 188 state_->delegate->DoDelayedWork(&delayed_work_time_);
269 // If we did not process any delayed work, then we can assume that our 189 // If we did not process any delayed work, then we can assume that our
270 // existing WM_TIMER if any will fire when delayed work should run. We 190 // existing WM_TIMER if any will fire when delayed work should run. We
271 // don't want to disturb that timer if it is already in flight. However, 191 // don't want to disturb that timer if it is already in flight. However,
272 // if we did do all remaining delayed work, then lets kill the WM_TIMER. 192 // if we did do all remaining delayed work, then lets kill the WM_TIMER.
273 if (more_work_is_plausible && delayed_work_time_.is_null()) 193 if (more_work_is_plausible && delayed_work_time_.is_null())
274 g_kill_timer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); 194 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
275 if (state_->should_quit) 195 if (state_->should_quit)
276 break; 196 break;
277 197
278 if (more_work_is_plausible) 198 if (more_work_is_plausible)
279 continue; 199 continue;
280 200
281 more_work_is_plausible = state_->delegate->DoIdleWork(); 201 more_work_is_plausible = state_->delegate->DoIdleWork();
282 if (state_->should_quit) 202 if (state_->should_quit)
283 break; 203 break;
284 204
285 if (more_work_is_plausible) 205 if (more_work_is_plausible)
286 continue; 206 continue;
287 207
288 WaitForWork(); // Wait (sleep) until we have work to do again. 208 WaitForWork(); // Wait (sleep) until we have work to do again.
289 } 209 }
290 } 210 }
291 211
292 void MessagePumpForUI::InitMessageWnd() { 212 void MessagePumpForUI::InitMessageWnd() {
293 // Generate a unique window class name. 213 // Generate a unique window class name.
294 string16 class_name = StringPrintf(kWndClassFormat, this); 214 string16 class_name = StringPrintf(kWndClassFormat, this);
295 215
296 HINSTANCE instance = CURRENT_MODULE(); 216 HINSTANCE instance = CURRENT_MODULE();
297 WNDCLASSEX wc = {0}; 217 WNDCLASSEX wc = {0};
298 wc.cbSize = sizeof(wc); 218 wc.cbSize = sizeof(wc);
299 wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>; 219 wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>;
300 wc.hInstance = instance; 220 wc.hInstance = instance;
301 wc.lpszClassName = class_name.c_str(); 221 wc.lpszClassName = class_name.c_str();
302 atom_ = g_register_class(&wc); 222 atom_ = RegisterClassEx(&wc);
303 DCHECK(atom_); 223 DCHECK(atom_);
304 224
305 message_hwnd_ = g_create_window_ex(0, MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0, 225 message_hwnd_ = CreateWindowEx(0, MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0,
306 HWND_MESSAGE, 0, instance, 0); 226 HWND_MESSAGE, 0, instance, 0);
307 DCHECK(message_hwnd_); 227 DCHECK(message_hwnd_);
308 } 228 }
309 229
310 void MessagePumpForUI::WaitForWork() { 230 void MessagePumpForUI::WaitForWork() {
311 // Wait until a message is available, up to the time needed by the timer 231 // Wait until a message is available, up to the time needed by the timer
312 // manager to fire the next set of timers. 232 // manager to fire the next set of timers.
313 int delay; 233 int delay;
314 DWORD wait_flags = MWMO_INPUTAVAILABLE; 234 DWORD wait_flags = MWMO_INPUTAVAILABLE;
315 235
316 while ((delay = GetCurrentDelay()) != 0) { 236 while ((delay = GetCurrentDelay()) != 0) {
317 if (delay < 0) // Negative value means no timers waiting. 237 if (delay < 0) // Negative value means no timers waiting.
318 delay = INFINITE; 238 delay = INFINITE;
319 239
320 DWORD result = g_msg_wait_for_multiple_objects_ex(0, nullptr, delay, 240 DWORD result = MsgWaitForMultipleObjectsEx(0, nullptr, delay, QS_ALLINPUT,
321 QS_ALLINPUT, wait_flags); 241 wait_flags);
322 242
323 if (WAIT_OBJECT_0 == result) { 243 if (WAIT_OBJECT_0 == result) {
324 // A WM_* message is available. 244 // A WM_* message is available.
325 // If a parent child relationship exists between windows across threads 245 // If a parent child relationship exists between windows across threads
326 // then their thread inputs are implicitly attached. 246 // then their thread inputs are implicitly attached.
327 // This causes the MsgWaitForMultipleObjectsEx API to return indicating 247 // This causes the MsgWaitForMultipleObjectsEx API to return indicating
328 // that messages are ready for processing (Specifically, mouse messages 248 // that messages are ready for processing (Specifically, mouse messages
329 // intended for the child window may appear if the child window has 249 // intended for the child window may appear if the child window has
330 // capture). 250 // capture).
331 // The subsequent PeekMessages call may fail to return any messages thus 251 // The subsequent PeekMessages call may fail to return any messages thus
332 // causing us to enter a tight loop at times. 252 // causing us to enter a tight loop at times.
333 // The code below is a workaround to give the child window 253 // The code below is a workaround to give the child window
334 // some time to process its input messages by looping back to 254 // some time to process its input messages by looping back to
335 // MsgWaitForMultipleObjectsEx above when there are no messages for the 255 // MsgWaitForMultipleObjectsEx above when there are no messages for the
336 // current thread. 256 // current thread.
337 MSG msg = {0}; 257 MSG msg = {0};
338 bool has_pending_sent_message = 258 bool has_pending_sent_message =
339 (HIWORD(g_get_queue_status(QS_SENDMESSAGE)) & QS_SENDMESSAGE) != 0; 259 (HIWORD(GetQueueStatus(QS_SENDMESSAGE)) & QS_SENDMESSAGE) != 0;
340 if (has_pending_sent_message || 260 if (has_pending_sent_message ||
341 g_peek_message(&msg, nullptr, 0, 0, PM_NOREMOVE)) { 261 PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) {
342 return; 262 return;
343 } 263 }
344 264
345 // We know there are no more messages for this thread because PeekMessage 265 // We know there are no more messages for this thread because PeekMessage
346 // has returned false. Reset |wait_flags| so that we wait for a *new* 266 // has returned false. Reset |wait_flags| so that we wait for a *new*
347 // message. 267 // message.
348 wait_flags = 0; 268 wait_flags = 0;
349 } 269 }
350 270
351 DCHECK_NE(WAIT_FAILED, result) << GetLastError(); 271 DCHECK_NE(WAIT_FAILED, result) << GetLastError();
(...skipping 17 matching lines...) Expand all
369 289
370 // Now give the delegate a chance to do some work. It'll let us know if it 290 // Now give the delegate a chance to do some work. It'll let us know if it
371 // needs to do more work. 291 // needs to do more work.
372 if (state_->delegate->DoWork()) 292 if (state_->delegate->DoWork())
373 ScheduleWork(); 293 ScheduleWork();
374 state_->delegate->DoDelayedWork(&delayed_work_time_); 294 state_->delegate->DoDelayedWork(&delayed_work_time_);
375 RescheduleTimer(); 295 RescheduleTimer();
376 } 296 }
377 297
378 void MessagePumpForUI::HandleTimerMessage() { 298 void MessagePumpForUI::HandleTimerMessage() {
379 g_kill_timer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); 299 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
380 300
381 // If we are being called outside of the context of Run, then don't do 301 // If we are being called outside of the context of Run, then don't do
382 // anything. This could correspond to a MessageBox call or something of 302 // anything. This could correspond to a MessageBox call or something of
383 // that sort. 303 // that sort.
384 if (!state_) 304 if (!state_)
385 return; 305 return;
386 306
387 state_->delegate->DoDelayedWork(&delayed_work_time_); 307 state_->delegate->DoDelayedWork(&delayed_work_time_);
388 RescheduleTimer(); 308 RescheduleTimer();
389 } 309 }
(...skipping 24 matching lines...) Expand all
414 int delay_msec = GetCurrentDelay(); 334 int delay_msec = GetCurrentDelay();
415 DCHECK_GE(delay_msec, 0); 335 DCHECK_GE(delay_msec, 0);
416 if (delay_msec == 0) { 336 if (delay_msec == 0) {
417 ScheduleWork(); 337 ScheduleWork();
418 } else { 338 } else {
419 if (delay_msec < USER_TIMER_MINIMUM) 339 if (delay_msec < USER_TIMER_MINIMUM)
420 delay_msec = USER_TIMER_MINIMUM; 340 delay_msec = USER_TIMER_MINIMUM;
421 341
422 // Create a WM_TIMER event that will wake us up to check for any pending 342 // Create a WM_TIMER event that will wake us up to check for any pending
423 // timers (in case we are running within a nested, external sub-pump). 343 // timers (in case we are running within a nested, external sub-pump).
424 BOOL ret = g_set_timer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), 344 BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this),
425 delay_msec, nullptr); 345 delay_msec, nullptr);
426 if (ret) 346 if (ret)
427 return; 347 return;
428 // If we can't set timers, we are in big trouble... but cross our fingers 348 // If we can't set timers, we are in big trouble... but cross our fingers
429 // for now. 349 // for now.
430 // TODO(jar): If we don't see this error, use a CHECK() here instead. 350 // TODO(jar): If we don't see this error, use a CHECK() here instead.
431 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, 351 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR,
432 MESSAGE_LOOP_PROBLEM_MAX); 352 MESSAGE_LOOP_PROBLEM_MAX);
433 } 353 }
434 } 354 }
435 355
436 bool MessagePumpForUI::ProcessNextWindowsMessage() { 356 bool MessagePumpForUI::ProcessNextWindowsMessage() {
437 // If there are sent messages in the queue then PeekMessage internally 357 // If there are sent messages in the queue then PeekMessage internally
438 // dispatches the message and returns false. We return true in this 358 // dispatches the message and returns false. We return true in this
439 // case to ensure that the message loop peeks again instead of calling 359 // case to ensure that the message loop peeks again instead of calling
440 // MsgWaitForMultipleObjectsEx again. 360 // MsgWaitForMultipleObjectsEx again.
441 bool sent_messages_in_queue = false; 361 bool sent_messages_in_queue = false;
442 DWORD queue_status = g_get_queue_status(QS_SENDMESSAGE); 362 DWORD queue_status = GetQueueStatus(QS_SENDMESSAGE);
443 if (HIWORD(queue_status) & QS_SENDMESSAGE) 363 if (HIWORD(queue_status) & QS_SENDMESSAGE)
444 sent_messages_in_queue = true; 364 sent_messages_in_queue = true;
445 365
446 MSG msg; 366 MSG msg;
447 if (g_peek_message(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE) 367 if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE)
448 return ProcessMessageHelper(msg); 368 return ProcessMessageHelper(msg);
449 369
450 return sent_messages_in_queue; 370 return sent_messages_in_queue;
451 } 371 }
452 372
453 bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { 373 bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) {
454 TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper", 374 TRACE_EVENT1("base", "MessagePumpForUI::ProcessMessageHelper",
455 "message", msg.message); 375 "message", msg.message);
456 if (WM_QUIT == msg.message) { 376 if (WM_QUIT == msg.message) {
457 // Receiving WM_QUIT is unusual and unexpected on most message loops. 377 // Receiving WM_QUIT is unusual and unexpected on most message loops.
458 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", 378 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem",
459 RECEIVED_WM_QUIT_ERROR, MESSAGE_LOOP_PROBLEM_MAX); 379 RECEIVED_WM_QUIT_ERROR, MESSAGE_LOOP_PROBLEM_MAX);
460 // Repost the QUIT message so that it will be retrieved by the primary 380 // Repost the QUIT message so that it will be retrieved by the primary
461 // GetMessage() loop. 381 // GetMessage() loop.
462 state_->should_quit = true; 382 state_->should_quit = true;
463 g_post_quit(static_cast<int>(msg.wParam)); 383 PostQuitMessage(static_cast<int>(msg.wParam));
464 return false; 384 return false;
465 } 385 }
466 386
467 // While running our main message pump, we discard kMsgHaveWork messages. 387 // While running our main message pump, we discard kMsgHaveWork messages.
468 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_) 388 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_)
469 return ProcessPumpReplacementMessage(); 389 return ProcessPumpReplacementMessage();
470 390
471 if (g_call_msg_filter(const_cast<MSG*>(&msg), kMessageFilterCode)) 391 if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode))
472 return true; 392 return true;
473 393
474 g_translate_message(&msg); 394 TranslateMessage(&msg);
475 g_dispatch_message(&msg); 395 DispatchMessage(&msg);
476 396
477 return true; 397 return true;
478 } 398 }
479 399
480 bool MessagePumpForUI::ProcessPumpReplacementMessage() { 400 bool MessagePumpForUI::ProcessPumpReplacementMessage() {
481 // When we encounter a kMsgHaveWork message, this method is called to peek and 401 // When we encounter a kMsgHaveWork message, this method is called to peek and
482 // process a replacement message. The goal is to make the kMsgHaveWork as non- 402 // process a replacement message. The goal is to make the kMsgHaveWork as non-
483 // intrusive as possible, even though a continuous stream of such messages are 403 // intrusive as possible, even though a continuous stream of such messages are
484 // posted. This method carefully peeks a message while there is no chance for 404 // posted. This method carefully peeks a message while there is no chance for
485 // a kMsgHaveWork to be pending, then resets the |have_work_| flag (allowing a 405 // a kMsgHaveWork to be pending, then resets the |have_work_| flag (allowing a
486 // replacement kMsgHaveWork to possibly be posted), and finally dispatches 406 // replacement kMsgHaveWork to possibly be posted), and finally dispatches
487 // that peeked replacement. Note that the re-post of kMsgHaveWork may be 407 // that peeked replacement. Note that the re-post of kMsgHaveWork may be
488 // asynchronous to this thread!! 408 // asynchronous to this thread!!
489 409
490 MSG msg; 410 MSG msg;
491 const bool have_message = 411 const bool have_message =
492 g_peek_message(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE; 412 PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != FALSE;
493 413
494 // Expect no message or a message different than kMsgHaveWork. 414 // Expect no message or a message different than kMsgHaveWork.
495 DCHECK(!have_message || kMsgHaveWork != msg.message || 415 DCHECK(!have_message || kMsgHaveWork != msg.message ||
496 msg.hwnd != message_hwnd_); 416 msg.hwnd != message_hwnd_);
497 417
498 // Since we discarded a kMsgHaveWork message, we must update the flag. 418 // Since we discarded a kMsgHaveWork message, we must update the flag.
499 int old_work_state_ = InterlockedExchange(&work_state_, READY); 419 int old_work_state_ = InterlockedExchange(&work_state_, READY);
500 DCHECK_EQ(HAVE_WORK, old_work_state_); 420 DCHECK_EQ(HAVE_WORK, old_work_state_);
501 421
502 // We don't need a special time slice if we didn't have_message to process. 422 // We don't need a special time slice if we didn't have_message to process.
503 if (!have_message) 423 if (!have_message)
504 return false; 424 return false;
505 425
506 // Guarantee we'll get another time slice in the case where we go into native 426 // Guarantee we'll get another time slice in the case where we go into native
507 // windows code. This ScheduleWork() may hurt performance a tiny bit when 427 // windows code. This ScheduleWork() may hurt performance a tiny bit when
508 // tasks appear very infrequently, but when the event queue is busy, the 428 // tasks appear very infrequently, but when the event queue is busy, the
509 // kMsgHaveWork events get (percentage wise) rarer and rarer. 429 // kMsgHaveWork events get (percentage wise) rarer and rarer.
510 ScheduleWork(); 430 ScheduleWork();
511 return ProcessMessageHelper(msg); 431 return ProcessMessageHelper(msg);
512 } 432 }
513 433
514 //----------------------------------------------------------------------------- 434 //-----------------------------------------------------------------------------
515 // MessagePumpForGpu public: 435 // MessagePumpForGpu public:
516 436
517 MessagePumpForGpu::MessagePumpForGpu() { 437 MessagePumpForGpu::MessagePumpForGpu() {
518 event_.Set(CreateEvent(nullptr, FALSE, FALSE, nullptr)); 438 event_.Set(CreateEvent(nullptr, FALSE, FALSE, nullptr));
519 InitUser32APIs();
520 } 439 }
521 440
522 MessagePumpForGpu::~MessagePumpForGpu() {} 441 MessagePumpForGpu::~MessagePumpForGpu() {}
523 442
524 // static 443 // static
525 void MessagePumpForGpu::InitFactory() { 444 void MessagePumpForGpu::InitFactory() {
526 bool init_result = MessageLoop::InitMessagePumpForUIFactory( 445 bool init_result = MessageLoop::InitMessagePumpForUIFactory(
527 &MessagePumpForGpu::CreateMessagePumpForGpu); 446 &MessagePumpForGpu::CreateMessagePumpForGpu);
528 DCHECK(init_result); 447 DCHECK(init_result);
529 } 448 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 delay = INFINITE; 532 delay = INFINITE;
614 533
615 // TODO(stanisc): crbug.com/596190: Preserve for crash dump analysis. 534 // TODO(stanisc): crbug.com/596190: Preserve for crash dump analysis.
616 // Remove this when the bug is fixed. 535 // Remove this when the bug is fixed.
617 TimeTicks wait_for_work_timeticks = TimeTicks::Now(); 536 TimeTicks wait_for_work_timeticks = TimeTicks::Now();
618 debug::Alias(&wait_for_work_timeticks); 537 debug::Alias(&wait_for_work_timeticks);
619 debug::Alias(&delay); 538 debug::Alias(&delay);
620 539
621 HANDLE handle = event_.Get(); 540 HANDLE handle = event_.Get();
622 DWORD result = 541 DWORD result =
623 g_msg_wait_for_multiple_objects_ex(1, &handle, delay, QS_ALLINPUT, 0); 542 MsgWaitForMultipleObjectsEx(1, &handle, delay, QS_ALLINPUT, 0);
624 DCHECK_NE(WAIT_FAILED, result) << GetLastError(); 543 DCHECK_NE(WAIT_FAILED, result) << GetLastError();
625 if (result != WAIT_TIMEOUT) { 544 if (result != WAIT_TIMEOUT) {
626 // Either work or message available. 545 // Either work or message available.
627 return; 546 return;
628 } 547 }
629 } 548 }
630 } 549 }
631 550
632 bool MessagePumpForGpu::ProcessNextMessage() { 551 bool MessagePumpForGpu::ProcessNextMessage() {
633 MSG msg; 552 MSG msg;
634 if (!g_peek_message(&msg, nullptr, 0, 0, PM_REMOVE)) 553 if (!PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
635 return false; 554 return false;
636 555
637 if (msg.message == WM_QUIT) { 556 if (msg.message == WM_QUIT) {
638 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", 557 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem",
639 RECEIVED_WM_QUIT_ERROR, MESSAGE_LOOP_PROBLEM_MAX); 558 RECEIVED_WM_QUIT_ERROR, MESSAGE_LOOP_PROBLEM_MAX);
640 // WM_QUIT messages shouldn't be received by any threads in the GPU 559 // WM_QUIT messages shouldn't be received by any threads in the GPU
641 // process. If they are, just ignore them instead of causing threads to 560 // process. If they are, just ignore them instead of causing threads to
642 // exit prematurely. 561 // exit prematurely.
643 return true; 562 return true;
644 } 563 }
645 564
646 if (!g_call_msg_filter(const_cast<MSG*>(&msg), kMessageFilterCode)) { 565 if (!CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) {
647 g_translate_message(&msg); 566 TranslateMessage(&msg);
648 g_dispatch_message(&msg); 567 DispatchMessage(&msg);
649 } 568 }
650 569
651 return true; 570 return true;
652 } 571 }
653 572
654 //----------------------------------------------------------------------------- 573 //-----------------------------------------------------------------------------
655 // MessagePumpForIO public: 574 // MessagePumpForIO public:
656 575
657 MessagePumpForIO::IOContext::IOContext() { 576 MessagePumpForIO::IOContext::IOContext() {
658 memset(&overlapped, 0, sizeof(overlapped)); 577 memset(&overlapped, 0, sizeof(overlapped));
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
823 if (!filter || it->handler == filter) { 742 if (!filter || it->handler == filter) {
824 *item = *it; 743 *item = *it;
825 completed_io_.erase(it); 744 completed_io_.erase(it);
826 return true; 745 return true;
827 } 746 }
828 } 747 }
829 return false; 748 return false;
830 } 749 }
831 750
832 } // namespace base 751 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698