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

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

Powered by Google App Engine
This is Rietveld 408576698