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

Side by Side Diff: base/message_loop/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_loop/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_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 8
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/message_loop/message_loop.h" 10 #include "base/message_loop/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 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 the attempt to acquire the lock fails, the message loop is shutting down
116 BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork, 119 // and the message window is about to be destroyed as well.
117 reinterpret_cast<WPARAM>(this), 0); 120 if (!message_hwnd_lock_.Try())
118 if (ret) 121 return;
119 return; // There was room in the Window Message queue. 122
123 {
124 base::AutoLock lock(message_hwnd_lock_, base::AutoLock::AlreadyAcquired());
125
126 // Do nothing if the window has been destroyed already.
127 if (!message_hwnd_)
128 return;
129
130 // Make sure the MessagePump does some work for us.
131 if (PostMessage(message_hwnd_, kMsgHaveWork,
132 reinterpret_cast<WPARAM>(this), 0)) {
133 return;
134 }
135 }
120 136
121 // We have failed to insert a have-work message, so there is a chance that we 137 // 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 138 // 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 139 // 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. :-( 140 // 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 141 // 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 142 // 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 143 // recovery. Nested loops are pretty transient (we think), so this will
128 // probably be recoverable. 144 // probably be recoverable.
129 InterlockedExchange(&have_work_, 0); // Clarify that we didn't really insert. 145 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); 181 delay_msec, NULL);
166 if (ret) 182 if (ret)
167 return; 183 return;
168 // If we can't set timers, we are in big trouble... but cross our fingers for 184 // If we can't set timers, we are in big trouble... but cross our fingers for
169 // now. 185 // now.
170 // TODO(jar): If we don't see this error, use a CHECK() here instead. 186 // TODO(jar): If we don't see this error, use a CHECK() here instead.
171 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR, 187 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", SET_TIMER_ERROR,
172 MESSAGE_LOOP_PROBLEM_MAX); 188 MESSAGE_LOOP_PROBLEM_MAX);
173 } 189 }
174 190
191 void MessagePumpForUI::Shutdown() {
192 HWND message_hwnd;
193 {
194 base::AutoLock lock(message_hwnd_lock_);
195
196 // Let ScheduleWork() know that the window has been destoyed.
197 message_hwnd = message_hwnd_;
198 message_hwnd_ = NULL;
199 }
200
201 // Destoy the window and its class. The destructor checks whether
202 // |message_hwnd_| and |atom_| are destroyed, so the variables should be
203 // cleared here.
204 DestroyWindow(message_hwnd);
205 UnregisterClass(MAKEINTATOM(atom_), GetModuleFromAddress(&WndProcThunk));
206 atom_ = 0;
207 }
208
175 void MessagePumpForUI::PumpOutPendingPaintMessages() { 209 void MessagePumpForUI::PumpOutPendingPaintMessages() {
176 // If we are being called outside of the context of Run, then don't try to do 210 // If we are being called outside of the context of Run, then don't try to do
177 // any work. 211 // any work.
178 if (!state_) 212 if (!state_)
179 return; 213 return;
180 214
181 // Create a mini-message-pump to force immediate processing of only Windows 215 // 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 216 // 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 217 // to get the job done. Actual common max is 4 peeks, but we'll be a little
184 // safe here. 218 // safe here.
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 return; // Someone else continued the pumping. 505 return; // Someone else continued the pumping.
472 506
473 // Make sure the MessagePump does some work for us. 507 // Make sure the MessagePump does some work for us.
474 BOOL ret = PostQueuedCompletionStatus(port_, 0, 508 BOOL ret = PostQueuedCompletionStatus(port_, 0,
475 reinterpret_cast<ULONG_PTR>(this), 509 reinterpret_cast<ULONG_PTR>(this),
476 reinterpret_cast<OVERLAPPED*>(this)); 510 reinterpret_cast<OVERLAPPED*>(this));
477 if (ret) 511 if (ret)
478 return; // Post worked perfectly. 512 return; // Post worked perfectly.
479 513
480 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery. 514 // See comment in MessagePumpForUI::ScheduleWork() for this error recovery.
481 InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed. 515 InterlockedExchange(&have_work_, 0);
482 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR, 516 UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR,
483 MESSAGE_LOOP_PROBLEM_MAX); 517 MESSAGE_LOOP_PROBLEM_MAX);
484 } 518 }
485 519
486 void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 520 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 521 // 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 522 // 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. 523 // how long to sleep when we do sleep.
490 delayed_work_time_ = delayed_work_time; 524 delayed_work_time_ = delayed_work_time;
491 } 525 }
492 526
527 void MessagePumpForIO::Shutdown() {
528 }
529
493 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, 530 void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle,
494 IOHandler* handler) { 531 IOHandler* handler) {
495 ULONG_PTR key = HandlerToKey(handler, true); 532 ULONG_PTR key = HandlerToKey(handler, true);
496 HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1); 533 HANDLE port = CreateIoCompletionPort(file_handle, port_, key, 1);
497 DPCHECK(port); 534 DPCHECK(port);
498 } 535 }
499 536
500 bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle, 537 bool MessagePumpForIO::RegisterJobObject(HANDLE job_handle,
501 IOHandler* handler) { 538 IOHandler* handler) {
502 // Job object notifications use the OVERLAPPED pointer to carry the message 539 // Job object notifications use the OVERLAPPED pointer to carry the message
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 714
678 // static 715 // static
679 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler( 716 MessagePumpForIO::IOHandler* MessagePumpForIO::KeyToHandler(
680 ULONG_PTR key, 717 ULONG_PTR key,
681 bool* has_valid_io_context) { 718 bool* has_valid_io_context) {
682 *has_valid_io_context = ((key & 1) == 0); 719 *has_valid_io_context = ((key & 1) == 0);
683 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1)); 720 return reinterpret_cast<IOHandler*>(key & ~static_cast<ULONG_PTR>(1));
684 } 721 }
685 722
686 } // namespace base 723 } // namespace base
OLDNEW
« no previous file with comments | « base/message_loop/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