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

Side by Side Diff: base/message_pump_win.cc

Issue 15709015: Make sure that the UI window created by base::MessagePumpForUI is destoyed on the same thread (Wind… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 7 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 | Annotate | Revision Log
« no previous file with comments | « base/message_pump_win.h ('k') | tools/valgrind/tsan/suppressions.txt » ('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_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" 12 #include "base/process_util.h"
13 #include "base/stringprintf.h" 13 #include "base/stringprintf.h"
14 #include "base/win/wrapped_window_proc.h" 14 #include "base/win/wrapped_window_proc.h"
15 15
16 namespace { 16 namespace {
17 17
18 enum MessageLoopProblems { 18 enum MessageLoopProblems {
19 MESSAGE_POST_ERROR, 19 MESSAGE_POST_ERROR,
20 COMPLETION_POST_ERROR, 20 COMPLETION_POST_ERROR,
21 SET_TIMER_ERROR, 21 SET_TIMER_ERROR,
22 MESSAGE_LOOP_PROBLEM_MAX, 22 MESSAGE_LOOP_PROBLEM_MAX,
23 }; 23 };
24 24
25 // Possible states of the message pump:
26 // - kPumpIdle: the thread is sleeping, waiting for work to be posted.
27 // - kPumpHaveWork: a window message or completion packet has been posted.
28 // - kPumpDisabled: the pump is disabled, no more work can be posted.
29 static const LONG kPumpIdle = 0;
30 static const LONG kPumpHaveWork = 1;
31 static const LONG kPumpDisabled = 2;
32
33 // Used to wake up the message loop thread in the case if it is waiting for
34 // another thread to exit MessagePumpForUI::ScheduleWork().
35 VOID CALLBACK DummyApc(ULONG_PTR) {}
36
25 } // namespace 37 } // namespace
26 38
27 namespace base { 39 namespace base {
28 40
29 static const wchar_t kWndClassFormat[] = L"Chrome_MessagePumpWindow_%p"; 41 static const wchar_t kWndClassFormat[] = L"Chrome_MessagePumpWindow_%p";
30 42
31 // Message sent to get an additional time slice for pumping (processing) another 43 // Message sent to get an additional time slice for pumping (processing) another
32 // task (a series of such messages creates a continuous task pump). 44 // task (a series of such messages creates a continuous task pump).
33 static const int kMsgHaveWork = WM_USER + 1; 45 static const int kMsgHaveWork = WM_USER + 1;
34 46
35 //----------------------------------------------------------------------------- 47 //-----------------------------------------------------------------------------
36 // MessagePumpWin public: 48 // MessagePumpWin public:
37 49
50 MessagePumpWin::MessagePumpWin() : pump_state_(kPumpIdle), state_(NULL) {}
51
38 void MessagePumpWin::AddObserver(MessagePumpObserver* observer) { 52 void MessagePumpWin::AddObserver(MessagePumpObserver* observer) {
39 observers_.AddObserver(observer); 53 observers_.AddObserver(observer);
40 } 54 }
41 55
42 void MessagePumpWin::RemoveObserver(MessagePumpObserver* observer) { 56 void MessagePumpWin::RemoveObserver(MessagePumpObserver* observer) {
43 observers_.RemoveObserver(observer); 57 observers_.RemoveObserver(observer);
44 } 58 }
45 59
46 void MessagePumpWin::WillProcessMessage(const MSG& msg) { 60 void MessagePumpWin::WillProcessMessage(const MSG& msg) {
47 FOR_EACH_OBSERVER(MessagePumpObserver, observers_, WillProcessEvent(msg)); 61 FOR_EACH_OBSERVER(MessagePumpObserver, observers_, WillProcessEvent(msg));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 106
93 return delay; 107 return delay;
94 } 108 }
95 109
96 //----------------------------------------------------------------------------- 110 //-----------------------------------------------------------------------------
97 // MessagePumpForUI public: 111 // MessagePumpForUI public:
98 112
99 MessagePumpForUI::MessagePumpForUI() 113 MessagePumpForUI::MessagePumpForUI()
100 : atom_(0), 114 : atom_(0),
101 message_filter_(new MessageFilter) { 115 message_filter_(new MessageFilter) {
116 CHECK(DuplicateHandle(GetCurrentProcess(),
117 GetCurrentThread(),
118 GetCurrentProcess(),
119 thread_.Receive(),
120 THREAD_SET_CONTEXT,
121 FALSE, // no not inherit this handle
122 0));
102 InitMessageWnd(); 123 InitMessageWnd();
103 } 124 }
104 125
105 MessagePumpForUI::~MessagePumpForUI() { 126 MessagePumpForUI::~MessagePumpForUI() {
106 DestroyWindow(message_hwnd_); 127 DCHECK(!atom_);
107 UnregisterClass(MAKEINTATOM(atom_), 128 DCHECK(!message_hwnd_);
108 base::GetModuleFromAddress(&WndProcThunk));
109 } 129 }
110 130
111 void MessagePumpForUI::ScheduleWork() { 131 void MessagePumpForUI::ScheduleWork() {
112 if (InterlockedExchange(&have_work_, 1)) 132 if (InterlockedCompareExchange(&pump_state_, kPumpHaveWork,
113 return; // Someone else continued the pumping. 133 kPumpIdle) != kPumpIdle) {
134 // Either someone else continued the pumping or the pump is disabled.
135 return;
136 }
114 137
115 // Make sure the MessagePump does some work for us. 138 // Make sure the MessagePump does some work for us.
116 BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork, 139 if (PostMessage(message_hwnd_, kMsgHaveWork, reinterpret_cast<WPARAM>(this),
117 reinterpret_cast<WPARAM>(this), 0); 140 0)) {
118 if (ret) 141 return;
119 return; // There was room in the Window Message queue. 142 }
120 143
121 // We have failed to insert a have-work message, so there is a chance that we 144 // 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 145 // 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 146 // 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. :-( 147 // 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 148 // 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 149 // 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 150 // recovery. Nested loops are pretty transient (we think), so this will
128 // probably be recoverable. 151 // probably be recoverable.
129 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert.
130 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR, 152 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", MESSAGE_POST_ERROR,
131 MESSAGE_LOOP_PROBLEM_MAX); 153 MESSAGE_LOOP_PROBLEM_MAX);
154
155
156
157 // Clarify that we didn't really insert.
158 InterlockedExchange(&pump_state_, kPumpIdle);
159
160 // Try to wake up the message loop thread by posting an APC. This might not
161 // work while a nested loop still running (see the comment above) but this
162 // will unblock WillDestroyCurrentMessageLoop() if it is waiting for
163 // ScheduleWork() to complete.
164 //
165 // According to the UMA metrics posting an I/O completion packet has very low
166 // error rate. Queuing an APC hits roughly the same path in the kernel so
167 // the error rate should be low as well. Given that we do it only when
168 // PostMessage() fails it should be safe to CHECK() here.
169 CHECK(QueueUserAPC(&DummyApc, thread_, 0));
132 } 170 }
133 171
134 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 172 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
135 // 173 //
136 // We would *like* to provide high resolution timers. Windows timers using 174 // We would *like* to provide high resolution timers. Windows timers using
137 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup 175 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup
138 // mechanism because the application can enter modal windows loops where it 176 // mechanism because the application can enter modal windows loops where it
139 // is not running our MessageLoop; the only way to have our timers fire in 177 // is not running our MessageLoop; the only way to have our timers fire in
140 // these cases is to post messages there. 178 // these cases is to post messages there.
141 // 179 //
(...skipping 23 matching lines...) Expand all
165 delay_msec, NULL); 203 delay_msec, NULL);
166 if (ret) 204 if (ret)
167 return; 205 return;
168 // If we can't set timers, we are in big trouble... but cross our fingers for 206 // If we can't set timers, we are in big trouble... but cross our fingers for
169 // now. 207 // now.
170 // TODO(jar): If we don't see this error, use a CHECK() here instead. 208 // TODO(jar): If we don't see this error, use a CHECK() here instead.
171 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, 209 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR,
172 MESSAGE_LOOP_PROBLEM_MAX); 210 MESSAGE_LOOP_PROBLEM_MAX);
173 } 211 }
174 212
213 void MessagePumpForUI::WillDestroyCurrentMessageLoop() {
214 // Disable the message pump. If |pump_state_ == kPumpHaveWork| then
215 // ScheduleWork() might be still running on a different thread. Wait until
216 // |kMsgHaveWork| is received or |pump_state_| is reset back to |kPumpIdle|.
217 while (InterlockedCompareExchange(&pump_state_, kPumpDisabled,
rvargas (doing something else) 2013/06/12 00:22:23 To be honest I prefer the version with a lock here
alexeypa (please no reviews) 2013/06/12 18:05:22 Well, Darin's reaction was exactly the opposite. H
rvargas (doing something else) 2013/06/12 18:24:24 Yes, I read all the comments on the original CL be
alexeypa (please no reviews) 2013/06/12 18:57:25 OK, fair enough. I resurrected the version with th
218 kPumpIdle) == kPumpHaveWork) {
219 MSG msg;
220 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
221 if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_) {
222 // Now that we received |kMsgHaveWork| the pump can be safely disabled.
223 InterlockedExchange(&pump_state_, kPumpDisabled);
224 break;
225 }
226 }
227
228 // Wait until |kMsgHaveWork| is posted or an APC is received.
229 WaitForWork();
230 }
231
232 // At this point the pump is disabled and other threads exited ScheduleWork().
233 DestroyWindow(message_hwnd_);
234 UnregisterClass(MAKEINTATOM(atom_),
235 base::GetModuleFromAddress(&WndProcThunk));
236
237 // Let the destructor know that the resources have been freed.
238 message_hwnd_ = NULL;
239 atom_ = 0;
240 }
241
175 void MessagePumpForUI::PumpOutPendingPaintMessages() { 242 void MessagePumpForUI::PumpOutPendingPaintMessages() {
176 // If we are being called outside of the context of Run, then don't try to do 243 // If we are being called outside of the context of Run, then don't try to do
177 // any work. 244 // any work.
178 if (!state_) 245 if (!state_)
179 return; 246 return;
180 247
181 // Create a mini-message-pump to force immediate processing of only Windows 248 // 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 249 // 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 250 // to get the job done. Actual common max is 4 peeks, but we'll be a little
184 // safe here. 251 // safe here.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
289 356
290 void MessagePumpForUI::WaitForWork() { 357 void MessagePumpForUI::WaitForWork() {
291 // Wait until a message is available, up to the time needed by the timer 358 // Wait until a message is available, up to the time needed by the timer
292 // manager to fire the next set of timers. 359 // manager to fire the next set of timers.
293 int delay = GetCurrentDelay(); 360 int delay = GetCurrentDelay();
294 if (delay < 0) // Negative value means no timers waiting. 361 if (delay < 0) // Negative value means no timers waiting.
295 delay = INFINITE; 362 delay = INFINITE;
296 363
297 DWORD result; 364 DWORD result;
298 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT, 365 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT,
299 MWMO_INPUTAVAILABLE); 366 MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
300 367
301 if (WAIT_OBJECT_0 == result) { 368 if (WAIT_OBJECT_0 == result) {
302 // A WM_* message is available. 369 // A WM_* message is available.
303 // If a parent child relationship exists between windows across threads 370 // If a parent child relationship exists between windows across threads
304 // then their thread inputs are implicitly attached. 371 // then their thread inputs are implicitly attached.
305 // This causes the MsgWaitForMultipleObjectsEx API to return indicating 372 // This causes the MsgWaitForMultipleObjectsEx API to return indicating
306 // that messages are ready for processing (Specifically, mouse messages 373 // that messages are ready for processing (Specifically, mouse messages
307 // intended for the child window may appear if the child window has 374 // intended for the child window may appear if the child window has
308 // capture). 375 // capture).
309 // The subsequent PeekMessages call may fail to return any messages thus 376 // The subsequent PeekMessages call may fail to return any messages thus
310 // causing us to enter a tight loop at times. 377 // causing us to enter a tight loop at times.
311 // The WaitMessage call below is a workaround to give the child window 378 // The WaitMessage call below is a workaround to give the child window
312 // some time to process its input messages. 379 // some time to process its input messages.
313 MSG msg = {0}; 380 MSG msg = {0};
314 DWORD queue_status = GetQueueStatus(QS_MOUSE); 381 DWORD queue_status = GetQueueStatus(QS_MOUSE);
315 if (HIWORD(queue_status) & QS_MOUSE && 382 if (HIWORD(queue_status) & QS_MOUSE &&
316 !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) { 383 !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) {
317 WaitMessage(); 384 WaitMessage();
318 } 385 }
319 return; 386 return;
387 } else if (WAIT_IO_COMPLETION == result) {
388 // The wait was ended by one or more APCs. It could be cause
389 // MessagePumpUI::ScheduleWork() is trying to wake up the message loop
390 // thread.
391 return;
320 } 392 }
321 393
322 DCHECK_NE(WAIT_FAILED, result) << GetLastError(); 394 DCHECK_NE(WAIT_FAILED, result) << GetLastError();
323 } 395 }
324 396
325 void MessagePumpForUI::HandleWorkMessage() { 397 void MessagePumpForUI::HandleWorkMessage() {
326 // If we are being called outside of the context of Run, then don't try to do 398 // If we are being called outside of the context of Run, then don't try to do
327 // any work. This could correspond to a MessageBox call or something of that 399 // any work. This could correspond to a MessageBox call or something of that
328 // sort. 400 // sort.
329 if (!state_) { 401 if (!state_) {
330 // Since we handled a kMsgHaveWork message, we must still update this flag. 402 // Since we handled a kMsgHaveWork message, we must still update this flag.
331 InterlockedExchange(&have_work_, 0); 403 InterlockedExchange(&pump_state_, kPumpIdle);
332 return; 404 return;
333 } 405 }
334 406
335 // Let whatever would have run had we not been putting messages in the queue 407 // Let whatever would have run had we not been putting messages in the queue
336 // run now. This is an attempt to make our dummy message not starve other 408 // run now. This is an attempt to make our dummy message not starve other
337 // messages that may be in the Windows message queue. 409 // messages that may be in the Windows message queue.
338 ProcessPumpReplacementMessage(); 410 ProcessPumpReplacementMessage();
339 411
340 // Now give the delegate a chance to do some work. He'll let us know if he 412 // Now give the delegate a chance to do some work. He'll let us know if he
341 // needs to do more work. 413 // needs to do more work.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 DidProcessMessage(msg); 481 DidProcessMessage(msg);
410 return true; 482 return true;
411 } 483 }
412 484
413 bool MessagePumpForUI::ProcessPumpReplacementMessage() { 485 bool MessagePumpForUI::ProcessPumpReplacementMessage() {
414 // When we encounter a kMsgHaveWork message, this method is called to peek 486 // When we encounter a kMsgHaveWork message, this method is called to peek
415 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The 487 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The
416 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though 488 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though
417 // a continuous stream of such messages are posted. This method carefully 489 // a continuous stream of such messages are posted. This method carefully
418 // peeks a message while there is no chance for a kMsgHaveWork to be pending, 490 // peeks a message while there is no chance for a kMsgHaveWork to be pending,
419 // then resets the have_work_ flag (allowing a replacement kMsgHaveWork to 491 // then resets the pump_state_ flag (allowing a replacement kMsgHaveWork to
420 // possibly be posted), and finally dispatches that peeked replacement. Note 492 // possibly be posted), and finally dispatches that peeked replacement. Note
421 // that the re-post of kMsgHaveWork may be asynchronous to this thread!! 493 // that the re-post of kMsgHaveWork may be asynchronous to this thread!!
422 494
423 bool have_message = false; 495 bool have_message = false;
424 MSG msg; 496 MSG msg;
425 // We should not process all window messages if we are in the context of an 497 // We should not process all window messages if we are in the context of an
426 // OS modal loop, i.e. in the context of a windows API call like MessageBox. 498 // OS modal loop, i.e. in the context of a windows API call like MessageBox.
427 // This is to ensure that these messages are peeked out by the OS modal loop. 499 // This is to ensure that these messages are peeked out by the OS modal loop.
428 if (MessageLoop::current()->os_modal_loop()) { 500 if (MessageLoop::current()->os_modal_loop()) {
429 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above. 501 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
430 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || 502 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
431 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE); 503 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
432 } else { 504 } else {
433 have_message = !!message_filter_->DoPeekMessage(&msg, NULL, 0, 0, 505 have_message = !!message_filter_->DoPeekMessage(&msg, NULL, 0, 0,
434 PM_REMOVE); 506 PM_REMOVE);
435 } 507 }
436 508
437 DCHECK(!have_message || kMsgHaveWork != msg.message || 509 DCHECK(!have_message || kMsgHaveWork != msg.message ||
438 msg.hwnd != message_hwnd_); 510 msg.hwnd != message_hwnd_);
439 511
440 // Since we discarded a kMsgHaveWork message, we must update the flag. 512 // Since we discarded a kMsgHaveWork message, we must update the flag.
441 int old_have_work = InterlockedExchange(&have_work_, 0); 513 int old_have_work = InterlockedExchange(&pump_state_, kPumpIdle);
442 DCHECK(old_have_work); 514 DCHECK(old_have_work);
443 515
444 // We don't need a special time slice if we didn't have_message to process. 516 // We don't need a special time slice if we didn't have_message to process.
445 if (!have_message) 517 if (!have_message)
446 return false; 518 return false;
447 519
448 // Guarantee we'll get another time slice in the case where we go into native 520 // Guarantee we'll get another time slice in the case where we go into native
449 // windows code. This ScheduleWork() may hurt performance a tiny bit when 521 // windows code. This ScheduleWork() may hurt performance a tiny bit when
450 // tasks appear very infrequently, but when the event queue is busy, the 522 // tasks appear very infrequently, but when the event queue is busy, the
451 // kMsgHaveWork events get (percentage wise) rarer and rarer. 523 // kMsgHaveWork events get (percentage wise) rarer and rarer.
452 ScheduleWork(); 524 ScheduleWork();
453 return ProcessMessageHelper(msg); 525 return ProcessMessageHelper(msg);
454 } 526 }
455 527
456 void MessagePumpForUI::SetMessageFilter( 528 void MessagePumpForUI::SetMessageFilter(
457 scoped_ptr<MessageFilter> message_filter) { 529 scoped_ptr<MessageFilter> message_filter) {
458 message_filter_ = message_filter.Pass(); 530 message_filter_ = message_filter.Pass();
459 } 531 }
460 532
461 //----------------------------------------------------------------------------- 533 //-----------------------------------------------------------------------------
462 // MessagePumpForIO public: 534 // MessagePumpForIO public:
463 535
464 MessagePumpForIO::MessagePumpForIO() { 536 MessagePumpForIO::MessagePumpForIO() {
465 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1)); 537 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1));
466 DCHECK(port_.IsValid()); 538 DCHECK(port_.IsValid());
467 } 539 }
468 540
469 void MessagePumpForIO::ScheduleWork() { 541 void MessagePumpForIO::ScheduleWork() {
470 if (InterlockedExchange(&have_work_, 1)) 542 if (InterlockedExchange(&pump_state_, kPumpHaveWork))
471 return; // Someone else continued the pumping. 543 return; // Someone else continued the pumping.
472 544
473 // Make sure the MessagePump does some work for us. 545 // Make sure the MessagePump does some work for us.
474 BOOL ret = PostQueuedCompletionStatus(port_, 0, 546 BOOL ret = PostQueuedCompletionStatus(port_, 0,
475 reinterpret_cast<ULONG_PTR>(this), 547 reinterpret_cast<ULONG_PTR>(this),
476 reinterpret_cast<OVERLAPPED*>(this)); 548 reinterpret_cast<OVERLAPPED*>(this));
477 if (ret) 549 if (ret)
478 return; // Post worked perfectly. 550 return; // Post worked perfectly.
479 551
480 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery. 552 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery.
481 InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed. 553 InterlockedExchange(&pump_state_, kPumpIdle);
482 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR, 554 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR,
483 MESSAGE_LOOP_PROBLEM_MAX); 555 MESSAGE_LOOP_PROBLEM_MAX);
484 } 556 }
485 557
486 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 558 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 559 // 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 560 // 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. 561 // how long to sleep when we do sleep.
490 delayed_work_time_ = delayed_work_time; 562 delayed_work_time_ = delayed_work_time;
491 } 563 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 item->handler = KeyToHandler(key, &item->has_valid_io_context); 688 item->handler = KeyToHandler(key, &item->has_valid_io_context);
617 item->context = reinterpret_cast<IOContext*>(overlapped); 689 item->context = reinterpret_cast<IOContext*>(overlapped);
618 return true; 690 return true;
619 } 691 }
620 692
621 bool MessagePumpForIO::ProcessInternalIOItem(const IOItem& item) { 693 bool MessagePumpForIO::ProcessInternalIOItem(const IOItem& item) {
622 if (this == reinterpret_cast<MessagePumpForIO*>(item.context) && 694 if (this == reinterpret_cast<MessagePumpForIO*>(item.context) &&
623 this == reinterpret_cast<MessagePumpForIO*>(item.handler)) { 695 this == reinterpret_cast<MessagePumpForIO*>(item.handler)) {
624 // This is our internal completion. 696 // This is our internal completion.
625 DCHECK(!item.bytes_transfered); 697 DCHECK(!item.bytes_transfered);
626 InterlockedExchange(&have_work_, 0); 698 InterlockedExchange(&pump_state_, kPumpIdle);
627 return true; 699 return true;
628 } 700 }
629 return false; 701 return false;
630 } 702 }
631 703
632 // Returns a completion item that was previously received. 704 // Returns a completion item that was previously received.
633 bool MessagePumpForIO::MatchCompletedIOItem(IOHandler* filter, IOItem* item) { 705 bool MessagePumpForIO::MatchCompletedIOItem(IOHandler* filter, IOItem* item) {
634 DCHECK(!completed_io_.empty()); 706 DCHECK(!completed_io_.empty());
635 for (std::list<IOItem>::iterator it = completed_io_.begin(); 707 for (std::list<IOItem>::iterator it = completed_io_.begin();
636 it != completed_io_.end(); ++it) { 708 it != completed_io_.end(); ++it) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 749
678 // static 750 // static
679 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( 751 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
680 ULONG_PTR key, 752 ULONG_PTR key,
681 bool* has_valid_io_context) { 753 bool* has_valid_io_context) {
682 *has_valid_io_context = ((key & 1) == 0); 754 *has_valid_io_context = ((key & 1) == 0);
683 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); 755 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
684 } 756 }
685 757
686 } // namespace base 758 } // namespace base
OLDNEW
« no previous file with comments | « base/message_pump_win.h ('k') | tools/valgrind/tsan/suppressions.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698