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

Side by Side Diff: base/message_pump_win.cc

Issue 10384209: Reverting r133134 - Make sure that base::MessagePumpForUI from different modules are isolated from … (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 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') | base/process_util.h » ('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/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
11 #include "base/stringprintf.h"
12 #include "base/win/wrapped_window_proc.h" 11 #include "base/win/wrapped_window_proc.h"
13 12
14 namespace {
15
16 // The ID of the timer used by the UI message pump.
17 const int kMessagePumpTimerId = 0;
18
19 } // namespace
20
21 namespace base { 13 namespace base {
22 14
23 static const wchar_t kWndClassFormat[] = L"Chrome_MessagePumpWindow%p"; 15 static const wchar_t kWndClass[] = L"Chrome_MessagePumpWindow";
24 16
25 // Message sent to get an additional time slice for pumping (processing) another 17 // Message sent to get an additional time slice for pumping (processing) another
26 // task (a series of such messages creates a continuous task pump). 18 // task (a series of such messages creates a continuous task pump).
27 static const int kMsgHaveWork = WM_USER + 1; 19 static const int kMsgHaveWork = WM_USER + 1;
28 20
29 //----------------------------------------------------------------------------- 21 //-----------------------------------------------------------------------------
30 // MessagePumpWin public: 22 // MessagePumpWin public:
31 23
32 void MessagePumpWin::AddObserver(MessagePumpObserver* observer) { 24 void MessagePumpWin::AddObserver(MessagePumpObserver* observer) {
33 observers_.AddObserver(observer); 25 observers_.AddObserver(observer);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 int delay = static_cast<int>(timeout); 75 int delay = static_cast<int>(timeout);
84 if (delay < 0) 76 if (delay < 0)
85 delay = 0; 77 delay = 0;
86 78
87 return delay; 79 return delay;
88 } 80 }
89 81
90 //----------------------------------------------------------------------------- 82 //-----------------------------------------------------------------------------
91 // MessagePumpForUI public: 83 // MessagePumpForUI public:
92 84
93 MessagePumpForUI::MessagePumpForUI() 85 MessagePumpForUI::MessagePumpForUI() {
94 : atom_(0),
95 instance_(NULL),
96 message_hwnd_(NULL) {
97 InitMessageWnd(); 86 InitMessageWnd();
98 } 87 }
99 88
100 MessagePumpForUI::~MessagePumpForUI() { 89 MessagePumpForUI::~MessagePumpForUI() {
101 if (message_hwnd_ != NULL) 90 DestroyWindow(message_hwnd_);
102 DestroyWindow(message_hwnd_); 91 UnregisterClass(kWndClass, GetModuleHandle(NULL));
103
104 if (atom_ != 0)
105 UnregisterClass(reinterpret_cast<const char16*>(atom_), instance_);
106 } 92 }
107 93
108 void MessagePumpForUI::ScheduleWork() { 94 void MessagePumpForUI::ScheduleWork() {
109 if (InterlockedExchange(&have_work_, 1)) 95 if (InterlockedExchange(&have_work_, 1))
110 return; // Someone else continued the pumping. 96 return; // Someone else continued the pumping.
111 97
112 // Make sure the MessagePump does some work for us. 98 // Make sure the MessagePump does some work for us.
113 PostMessage(message_hwnd_, kMsgHaveWork, 0, 0); 99 PostMessage(message_hwnd_, kMsgHaveWork, reinterpret_cast<WPARAM>(this), 0);
114 } 100 }
115 101
116 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { 102 void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
117 // 103 //
118 // We would *like* to provide high resolution timers. Windows timers using 104 // We would *like* to provide high resolution timers. Windows timers using
119 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup 105 // SetTimer() have a 10ms granularity. We have to use WM_TIMER as a wakeup
120 // mechanism because the application can enter modal windows loops where it 106 // mechanism because the application can enter modal windows loops where it
121 // is not running our MessageLoop; the only way to have our timers fire in 107 // is not running our MessageLoop; the only way to have our timers fire in
122 // these cases is to post messages there. 108 // these cases is to post messages there.
123 // 109 //
(...skipping 12 matching lines...) Expand all
136 // 122 //
137 delayed_work_time_ = delayed_work_time; 123 delayed_work_time_ = delayed_work_time;
138 124
139 int delay_msec = GetCurrentDelay(); 125 int delay_msec = GetCurrentDelay();
140 DCHECK_GE(delay_msec, 0); 126 DCHECK_GE(delay_msec, 0);
141 if (delay_msec < USER_TIMER_MINIMUM) 127 if (delay_msec < USER_TIMER_MINIMUM)
142 delay_msec = USER_TIMER_MINIMUM; 128 delay_msec = USER_TIMER_MINIMUM;
143 129
144 // Create a WM_TIMER event that will wake us up to check for any pending 130 // Create a WM_TIMER event that will wake us up to check for any pending
145 // timers (in case we are running within a nested, external sub-pump). 131 // timers (in case we are running within a nested, external sub-pump).
146 SetTimer(message_hwnd_, kMessagePumpTimerId, delay_msec, NULL); 132 SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), delay_msec, NULL);
147 } 133 }
148 134
149 void MessagePumpForUI::PumpOutPendingPaintMessages() { 135 void MessagePumpForUI::PumpOutPendingPaintMessages() {
150 // If we are being called outside of the context of Run, then don't try to do 136 // If we are being called outside of the context of Run, then don't try to do
151 // any work. 137 // any work.
152 if (!state_) 138 if (!state_)
153 return; 139 return;
154 140
155 // Create a mini-message-pump to force immediate processing of only Windows 141 // Create a mini-message-pump to force immediate processing of only Windows
156 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking 142 // WM_PAINT messages. Don't provide an infinite loop, but do enough peeking
(...skipping 12 matching lines...) Expand all
169 // Histogram what was really being used, to help to adjust kMaxPeekCount. 155 // Histogram what was really being used, to help to adjust kMaxPeekCount.
170 DHISTOGRAM_COUNTS("Loop.PumpOutPendingPaintMessages Peeks", peek_count); 156 DHISTOGRAM_COUNTS("Loop.PumpOutPendingPaintMessages Peeks", peek_count);
171 } 157 }
172 158
173 //----------------------------------------------------------------------------- 159 //-----------------------------------------------------------------------------
174 // MessagePumpForUI private: 160 // MessagePumpForUI private:
175 161
176 // static 162 // static
177 LRESULT CALLBACK MessagePumpForUI::WndProcThunk( 163 LRESULT CALLBACK MessagePumpForUI::WndProcThunk(
178 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { 164 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
179 // Retrieve |this| from the user data, associated with the window. 165 switch (message) {
180 MessagePumpForUI* self = reinterpret_cast<MessagePumpForUI*>( 166 case kMsgHaveWork:
181 GetWindowLongPtr(hwnd, GWLP_USERDATA)); 167 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage();
182 if (self != NULL) { 168 break;
183 switch (message) { 169 case WM_TIMER:
184 case kMsgHaveWork: 170 reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage();
185 self->HandleWorkMessage(); 171 break;
186 break;
187 case WM_TIMER:
188 DCHECK(wparam == kMessagePumpTimerId);
189 self->HandleTimerMessage();
190 break;
191 }
192 } 172 }
193 return DefWindowProc(hwnd, message, wparam, lparam); 173 return DefWindowProc(hwnd, message, wparam, lparam);
194 } 174 }
195 175
196 void MessagePumpForUI::DoRunLoop() { 176 void MessagePumpForUI::DoRunLoop() {
197 // IF this was just a simple PeekMessage() loop (servicing all possible work 177 // IF this was just a simple PeekMessage() loop (servicing all possible work
198 // queues), then Windows would try to achieve the following order according 178 // queues), then Windows would try to achieve the following order according
199 // to MSDN documentation about PeekMessage with no filter): 179 // to MSDN documentation about PeekMessage with no filter):
200 // * Sent messages 180 // * Sent messages
201 // * Posted messages 181 // * Posted messages
(...skipping 22 matching lines...) Expand all
224 if (state_->should_quit) 204 if (state_->should_quit)
225 break; 205 break;
226 206
227 more_work_is_plausible |= 207 more_work_is_plausible |=
228 state_->delegate->DoDelayedWork(&delayed_work_time_); 208 state_->delegate->DoDelayedWork(&delayed_work_time_);
229 // If we did not process any delayed work, then we can assume that our 209 // If we did not process any delayed work, then we can assume that our
230 // existing WM_TIMER if any will fire when delayed work should run. We 210 // existing WM_TIMER if any will fire when delayed work should run. We
231 // don't want to disturb that timer if it is already in flight. However, 211 // don't want to disturb that timer if it is already in flight. However,
232 // if we did do all remaining delayed work, then lets kill the WM_TIMER. 212 // if we did do all remaining delayed work, then lets kill the WM_TIMER.
233 if (more_work_is_plausible && delayed_work_time_.is_null()) 213 if (more_work_is_plausible && delayed_work_time_.is_null())
234 KillTimer(message_hwnd_, kMessagePumpTimerId); 214 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
235 if (state_->should_quit) 215 if (state_->should_quit)
236 break; 216 break;
237 217
238 if (more_work_is_plausible) 218 if (more_work_is_plausible)
239 continue; 219 continue;
240 220
241 more_work_is_plausible = state_->delegate->DoIdleWork(); 221 more_work_is_plausible = state_->delegate->DoIdleWork();
242 if (state_->should_quit) 222 if (state_->should_quit)
243 break; 223 break;
244 224
245 if (more_work_is_plausible) 225 if (more_work_is_plausible)
246 continue; 226 continue;
247 227
248 WaitForWork(); // Wait (sleep) until we have work to do again. 228 WaitForWork(); // Wait (sleep) until we have work to do again.
249 } 229 }
250 } 230 }
251 231
252 void MessagePumpForUI::InitMessageWnd() { 232 void MessagePumpForUI::InitMessageWnd() {
253 // Register a unique window class for each instance of UI pump. 233 HINSTANCE hinst = GetModuleHandle(NULL);
254 string16 class_name = base::StringPrintf(kWndClassFormat, this);
255 WNDCLASSEX window_class;
256 base::win::InitializeWindowClass(
257 class_name.c_str(),
258 &base::win::WrappedWindowProc<WndProcThunk>,
259 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
260 &window_class);
261 instance_ = window_class.hInstance;
262 atom_ = RegisterClassEx(&window_class);
263 if (atom_ == 0) {
264 DCHECK(atom_);
265 return;
266 }
267 234
268 // Create the message-only window. 235 WNDCLASSEX wc = {0};
269 message_hwnd_ = CreateWindow( 236 wc.cbSize = sizeof(wc);
270 MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, instance_, 0); 237 wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>;
271 if (message_hwnd_ == NULL) { 238 wc.hInstance = hinst;
272 DCHECK(message_hwnd_); 239 wc.lpszClassName = kWndClass;
273 return; 240 RegisterClassEx(&wc);
274 }
275 241
276 // Store |this| so that the window procedure could retrieve it later. 242 message_hwnd_ =
277 SetWindowLongPtr(message_hwnd_, 243 CreateWindow(kWndClass, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, hinst, 0);
278 GWLP_USERDATA, 244 DCHECK(message_hwnd_);
279 reinterpret_cast<LONG_PTR>(this));
280 } 245 }
281 246
282 void MessagePumpForUI::WaitForWork() { 247 void MessagePumpForUI::WaitForWork() {
283 // Wait until a message is available, up to the time needed by the timer 248 // Wait until a message is available, up to the time needed by the timer
284 // manager to fire the next set of timers. 249 // manager to fire the next set of timers.
285 int delay = GetCurrentDelay(); 250 int delay = GetCurrentDelay();
286 if (delay < 0) // Negative value means no timers waiting. 251 if (delay < 0) // Negative value means no timers waiting.
287 delay = INFINITE; 252 delay = INFINITE;
288 253
289 DWORD result; 254 DWORD result;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 // messages that may be in the Windows message queue. 293 // messages that may be in the Windows message queue.
329 ProcessPumpReplacementMessage(); 294 ProcessPumpReplacementMessage();
330 295
331 // Now give the delegate a chance to do some work. He'll let us know if he 296 // Now give the delegate a chance to do some work. He'll let us know if he
332 // needs to do more work. 297 // needs to do more work.
333 if (state_->delegate->DoWork()) 298 if (state_->delegate->DoWork())
334 ScheduleWork(); 299 ScheduleWork();
335 } 300 }
336 301
337 void MessagePumpForUI::HandleTimerMessage() { 302 void MessagePumpForUI::HandleTimerMessage() {
338 KillTimer(message_hwnd_, kMessagePumpTimerId); 303 KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
339 304
340 // If we are being called outside of the context of Run, then don't do 305 // If we are being called outside of the context of Run, then don't do
341 // anything. This could correspond to a MessageBox call or something of 306 // anything. This could correspond to a MessageBox call or something of
342 // that sort. 307 // that sort.
343 if (!state_) 308 if (!state_)
344 return; 309 return;
345 310
346 state_->delegate->DoDelayedWork(&delayed_work_time_); 311 state_->delegate->DoDelayedWork(&delayed_work_time_);
347 if (!delayed_work_time_.is_null()) { 312 if (!delayed_work_time_.is_null()) {
348 // A bit gratuitous to set delayed_work_time_ again, but oh well. 313 // A bit gratuitous to set delayed_work_time_ again, but oh well.
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 574
610 void MessagePumpForIO::WillProcessIOEvent() { 575 void MessagePumpForIO::WillProcessIOEvent() {
611 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent()); 576 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
612 } 577 }
613 578
614 void MessagePumpForIO::DidProcessIOEvent() { 579 void MessagePumpForIO::DidProcessIOEvent() {
615 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); 580 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
616 } 581 }
617 582
618 } // namespace base 583 } // namespace base
OLDNEW
« no previous file with comments | « base/message_pump_win.h ('k') | base/process_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698