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

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: 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
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;
rvargas (doing something else) 2013/06/12 00:22:22 nit: don't need static
alexeypa (please no reviews) 2013/06/12 18:05:22 Done.
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
rvargas (doing something else) 2013/06/12 00:22:22 nit: remove "in the case"
alexeypa (please no reviews) 2013/06/12 18:05:22 Done.
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
rvargas (doing something else) 2013/06/12 00:22:22 fix comment
alexeypa (please no reviews) 2013/06/12 18:05:22 Done.
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,
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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 357
291 void MessagePumpForUI::WaitForWork() { 358 void MessagePumpForUI::WaitForWork() {
292 // Wait until a message is available, up to the time needed by the timer 359 // Wait until a message is available, up to the time needed by the timer
293 // manager to fire the next set of timers. 360 // manager to fire the next set of timers.
294 int delay = GetCurrentDelay(); 361 int delay = GetCurrentDelay();
295 if (delay < 0) // Negative value means no timers waiting. 362 if (delay < 0) // Negative value means no timers waiting.
296 delay = INFINITE; 363 delay = INFINITE;
297 364
298 DWORD result; 365 DWORD result;
299 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT, 366 result = MsgWaitForMultipleObjectsEx(0, NULL, delay, QS_ALLINPUT,
300 MWMO_INPUTAVAILABLE); 367 MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
301 368
302 if (WAIT_OBJECT_0 == result) { 369 if (WAIT_OBJECT_0 == result) {
303 // A WM_* message is available. 370 // A WM_* message is available.
304 // If a parent child relationship exists between windows across threads 371 // If a parent child relationship exists between windows across threads
305 // then their thread inputs are implicitly attached. 372 // then their thread inputs are implicitly attached.
306 // This causes the MsgWaitForMultipleObjectsEx API to return indicating 373 // This causes the MsgWaitForMultipleObjectsEx API to return indicating
307 // that messages are ready for processing (Specifically, mouse messages 374 // that messages are ready for processing (Specifically, mouse messages
308 // intended for the child window may appear if the child window has 375 // intended for the child window may appear if the child window has
309 // capture). 376 // capture).
310 // The subsequent PeekMessages call may fail to return any messages thus 377 // The subsequent PeekMessages call may fail to return any messages thus
311 // causing us to enter a tight loop at times. 378 // causing us to enter a tight loop at times.
312 // The WaitMessage call below is a workaround to give the child window 379 // The WaitMessage call below is a workaround to give the child window
313 // some time to process its input messages. 380 // some time to process its input messages.
314 MSG msg = {0}; 381 MSG msg = {0};
315 DWORD queue_status = GetQueueStatus(QS_MOUSE); 382 DWORD queue_status = GetQueueStatus(QS_MOUSE);
316 if (HIWORD(queue_status) & QS_MOUSE && 383 if (HIWORD(queue_status) & QS_MOUSE &&
317 !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) { 384 !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) {
318 WaitMessage(); 385 WaitMessage();
319 } 386 }
320 return; 387 return;
388 } else if (WAIT_IO_COMPLETION == result) {
389 // The wait was ended by one or more APCs. It could be cause
390 // MessagePumpUI::ScheduleWork() is trying to wake up the message loop
391 // thread.
392 return;
321 } 393 }
322 394
323 DCHECK_NE(WAIT_FAILED, result) << GetLastError(); 395 DCHECK_NE(WAIT_FAILED, result) << GetLastError();
324 } 396 }
325 397
326 void MessagePumpForUI::HandleWorkMessage() { 398 void MessagePumpForUI::HandleWorkMessage() {
327 // If we are being called outside of the context of Run, then don't try to do 399 // If we are being called outside of the context of Run, then don't try to do
328 // any work. This could correspond to a MessageBox call or something of that 400 // any work. This could correspond to a MessageBox call or something of that
329 // sort. 401 // sort.
330 if (!state_) { 402 if (!state_) {
331 // Since we handled a kMsgHaveWork message, we must still update this flag. 403 // Since we handled a kMsgHaveWork message, we must still update this flag.
332 InterlockedExchange(&have_work_, 0); 404 InterlockedExchange(&pump_state_, kPumpIdle);
333 return; 405 return;
334 } 406 }
335 407
336 // Let whatever would have run had we not been putting messages in the queue 408 // Let whatever would have run had we not been putting messages in the queue
337 // run now. This is an attempt to make our dummy message not starve other 409 // run now. This is an attempt to make our dummy message not starve other
338 // messages that may be in the Windows message queue. 410 // messages that may be in the Windows message queue.
339 ProcessPumpReplacementMessage(); 411 ProcessPumpReplacementMessage();
340 412
341 // Now give the delegate a chance to do some work. He'll let us know if he 413 // Now give the delegate a chance to do some work. He'll let us know if he
342 // needs to do more work. 414 // needs to do more work.
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 DidProcessMessage(msg); 482 DidProcessMessage(msg);
411 return true; 483 return true;
412 } 484 }
413 485
414 bool MessagePumpForUI::ProcessPumpReplacementMessage() { 486 bool MessagePumpForUI::ProcessPumpReplacementMessage() {
415 // When we encounter a kMsgHaveWork message, this method is called to peek 487 // When we encounter a kMsgHaveWork message, this method is called to peek
416 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The 488 // and process a replacement message, such as a WM_PAINT or WM_TIMER. The
417 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though 489 // goal is to make the kMsgHaveWork as non-intrusive as possible, even though
418 // a continuous stream of such messages are posted. This method carefully 490 // a continuous stream of such messages are posted. This method carefully
419 // peeks a message while there is no chance for a kMsgHaveWork to be pending, 491 // peeks a message while there is no chance for a kMsgHaveWork to be pending,
420 // then resets the have_work_ flag (allowing a replacement kMsgHaveWork to 492 // then resets the pump_state_ flag (allowing a replacement kMsgHaveWork to
rvargas (doing something else) 2013/06/12 00:22:22 nit: not a flag to be reset anymore.
alexeypa (please no reviews) 2013/06/12 18:05:22 Done.
421 // possibly be posted), and finally dispatches that peeked replacement. Note 493 // possibly be posted), and finally dispatches that peeked replacement. Note
422 // that the re-post of kMsgHaveWork may be asynchronous to this thread!! 494 // that the re-post of kMsgHaveWork may be asynchronous to this thread!!
423 495
424 bool have_message = false; 496 bool have_message = false;
425 MSG msg; 497 MSG msg;
426 // We should not process all window messages if we are in the context of an 498 // We should not process all window messages if we are in the context of an
427 // OS modal loop, i.e. in the context of a windows API call like MessageBox. 499 // OS modal loop, i.e. in the context of a windows API call like MessageBox.
428 // This is to ensure that these messages are peeked out by the OS modal loop. 500 // This is to ensure that these messages are peeked out by the OS modal loop.
429 if (MessageLoop::current()->os_modal_loop()) { 501 if (MessageLoop::current()->os_modal_loop()) {
430 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above. 502 // We only peek out WM_PAINT and WM_TIMER here for reasons mentioned above.
431 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) || 503 have_message = PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE) ||
432 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE); 504 PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
433 } else { 505 } else {
434 have_message = !!message_filter_->DoPeekMessage(&msg, NULL, 0, 0, 506 have_message = !!message_filter_->DoPeekMessage(&msg, NULL, 0, 0,
435 PM_REMOVE); 507 PM_REMOVE);
436 } 508 }
437 509
438 DCHECK(!have_message || kMsgHaveWork != msg.message || 510 DCHECK(!have_message || kMsgHaveWork != msg.message ||
439 msg.hwnd != message_hwnd_); 511 msg.hwnd != message_hwnd_);
440 512
441 // Since we discarded a kMsgHaveWork message, we must update the flag. 513 // Since we discarded a kMsgHaveWork message, we must update the flag.
442 int old_have_work = InterlockedExchange(&have_work_, 0); 514 int old_have_work = InterlockedExchange(&pump_state_, kPumpIdle);
443 DCHECK(old_have_work); 515 DCHECK(old_have_work);
444 516
445 // We don't need a special time slice if we didn't have_message to process. 517 // We don't need a special time slice if we didn't have_message to process.
446 if (!have_message) 518 if (!have_message)
447 return false; 519 return false;
448 520
449 // Guarantee we'll get another time slice in the case where we go into native 521 // Guarantee we'll get another time slice in the case where we go into native
450 // windows code. This ScheduleWork() may hurt performance a tiny bit when 522 // windows code. This ScheduleWork() may hurt performance a tiny bit when
451 // tasks appear very infrequently, but when the event queue is busy, the 523 // tasks appear very infrequently, but when the event queue is busy, the
452 // kMsgHaveWork events get (percentage wise) rarer and rarer. 524 // kMsgHaveWork events get (percentage wise) rarer and rarer.
453 ScheduleWork(); 525 ScheduleWork();
454 return ProcessMessageHelper(msg); 526 return ProcessMessageHelper(msg);
455 } 527 }
456 528
457 void MessagePumpForUI::SetMessageFilter( 529 void MessagePumpForUI::SetMessageFilter(
458 scoped_ptr<MessageFilter> message_filter) { 530 scoped_ptr<MessageFilter> message_filter) {
459 message_filter_ = message_filter.Pass(); 531 message_filter_ = message_filter.Pass();
460 } 532 }
461 533
462 //----------------------------------------------------------------------------- 534 //-----------------------------------------------------------------------------
463 // MessagePumpForIO public: 535 // MessagePumpForIO public:
464 536
465 MessagePumpForIO::MessagePumpForIO() { 537 MessagePumpForIO::MessagePumpForIO() {
466 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1)); 538 port_.Set(CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1));
467 DCHECK(port_.IsValid()); 539 DCHECK(port_.IsValid());
468 } 540 }
469 541
470 void MessagePumpForIO::ScheduleWork() { 542 void MessagePumpForIO::ScheduleWork() {
471 if (InterlockedExchange(&have_work_, 1)) 543 if (InterlockedExchange(&pump_state_, kPumpHaveWork))
472 return; // Someone else continued the pumping. 544 return; // Someone else continued the pumping.
473 545
474 // Make sure the MessagePump does some work for us. 546 // Make sure the MessagePump does some work for us.
475 BOOL ret = PostQueuedCompletionStatus(port_, 0, 547 BOOL ret = PostQueuedCompletionStatus(port_, 0,
476 reinterpret_cast<ULONG_PTR>(this), 548 reinterpret_cast<ULONG_PTR>(this),
477 reinterpret_cast<OVERLAPPED*>(this)); 549 reinterpret_cast<OVERLAPPED*>(this));
478 if (ret) 550 if (ret)
479 return; // Post worked perfectly. 551 return; // Post worked perfectly.
480 552
481 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery. 553 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery.
482 InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed. 554 InterlockedExchange(&pump_state_, kPumpIdle);
483 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR, 555 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR,
484 MESSAGE_LOOP_PROBLEM_MAX); 556 MESSAGE_LOOP_PROBLEM_MAX);
485 } 557 }
486 558
487 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 559 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
488 // We know that we can't be blocked right now since this method can only be 560 // We know that we can't be blocked right now since this method can only be
489 // called on the same thread as Run, so we only need to update our record of 561 // called on the same thread as Run, so we only need to update our record of
490 // how long to sleep when we do sleep. 562 // how long to sleep when we do sleep.
491 delayed_work_time_ = delayed_work_time; 563 delayed_work_time_ = delayed_work_time;
492 } 564 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 item->handler = KeyToHandler(key, &item->has_valid_io_context); 689 item->handler = KeyToHandler(key, &item->has_valid_io_context);
618 item->context = reinterpret_cast<IOContext*>(overlapped); 690 item->context = reinterpret_cast<IOContext*>(overlapped);
619 return true; 691 return true;
620 } 692 }
621 693
622 bool MessagePumpForIO::ProcessInternalIOItem(const IOItem& item) { 694 bool MessagePumpForIO::ProcessInternalIOItem(const IOItem& item) {
623 if (this == reinterpret_cast<MessagePumpForIO*>(item.context) && 695 if (this == reinterpret_cast<MessagePumpForIO*>(item.context) &&
624 this == reinterpret_cast<MessagePumpForIO*>(item.handler)) { 696 this == reinterpret_cast<MessagePumpForIO*>(item.handler)) {
625 // This is our internal completion. 697 // This is our internal completion.
626 DCHECK(!item.bytes_transfered); 698 DCHECK(!item.bytes_transfered);
627 InterlockedExchange(&have_work_, 0); 699 InterlockedExchange(&pump_state_, kPumpIdle);
628 return true; 700 return true;
629 } 701 }
630 return false; 702 return false;
631 } 703 }
632 704
633 // Returns a completion item that was previously received. 705 // Returns a completion item that was previously received.
634 bool MessagePumpForIO::MatchCompletedIOItem(IOHandler* filter, IOItem* item) { 706 bool MessagePumpForIO::MatchCompletedIOItem(IOHandler* filter, IOItem* item) {
635 DCHECK(!completed_io_.empty()); 707 DCHECK(!completed_io_.empty());
636 for (std::list<IOItem>::iterator it = completed_io_.begin(); 708 for (std::list<IOItem>::iterator it = completed_io_.begin();
637 it != completed_io_.end(); ++it) { 709 it != completed_io_.end(); ++it) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 750
679 // static 751 // static
680 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( 752 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
681 ULONG_PTR key, 753 ULONG_PTR key,
682 bool* has_valid_io_context) { 754 bool* has_valid_io_context) {
683 *has_valid_io_context = ((key & 1) == 0); 755 *has_valid_io_context = ((key & 1) == 0);
684 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); 756 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
685 } 757 }
686 758
687 } // namespace base 759 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698