diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-24 01:34:51 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-24 01:34:51 +0000 |
commit | d5eb9ccc118f56565325cff1cbb24571511d1925 (patch) | |
tree | e5b9c05d2954b4c1f416970c8647463587aa73a1 /base/message_pump_win.cc | |
parent | 3214fd26bb2ccd17e2611f69c895f4b43cf87bf1 (diff) | |
download | chromium_src-d5eb9ccc118f56565325cff1cbb24571511d1925.zip chromium_src-d5eb9ccc118f56565325cff1cbb24571511d1925.tar.gz chromium_src-d5eb9ccc118f56565325cff1cbb24571511d1925.tar.bz2 |
Allow multiple base::MessagePumpForUI instances to be created simultanenously on Windows.
The current implementation of base::MessagePumpForUI on Windows registers a window class with a predefined name in order to create a message-only window. The window class is unregistered when base::MessagePumpForUI is deleted. This causes issues when two or more instances of base::MessagePumpForUI are created/destroyed simultanenously on different threads. For instance once thread can unregister the window class right before the other thread is trying to create a window using this class.
The CL addresses this problem by switching MessageWindow to implement a message-only window. It also moves MessageWindow from remoting/host/win to base/win along with the corresponding unit test.
MessageWindow registers a uniquely named window class per MessageWindow instance making sure that different MessageWindow objects do not share any resources. In the future this can be optimized further by registering a common window class shared by all MessageWindow objects in a thread-safe manner (by using LazyInstance for example).
BUG=241939
Review URL: https://chromiumcodereview.appspot.com/15261005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@201955 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/message_pump_win.cc')
-rw-r--r-- | base/message_pump_win.cc | 60 |
1 files changed, 23 insertions, 37 deletions
diff --git a/base/message_pump_win.cc b/base/message_pump_win.cc index fb962ca..e6ac6d0 100644 --- a/base/message_pump_win.cc +++ b/base/message_pump_win.cc @@ -9,8 +9,6 @@ #include "base/debug/trace_event.h" #include "base/message_loop.h" #include "base/metrics/histogram.h" -#include "base/process_util.h" -#include "base/win/wrapped_window_proc.h" namespace { @@ -25,12 +23,13 @@ enum MessageLoopProblems { namespace base { -static const wchar_t kWndClass[] = L"Chrome_MessagePumpWindow"; - // Message sent to get an additional time slice for pumping (processing) another // task (a series of such messages creates a continuous task pump). static const int kMsgHaveWork = WM_USER + 1; +// Used by MessagePumpUI to wake up the thread and check any pending timers. +static const int kTimerId = 1; + //----------------------------------------------------------------------------- // MessagePumpWin public: @@ -96,14 +95,12 @@ int MessagePumpWin::GetCurrentDelay() const { // MessagePumpForUI public: MessagePumpForUI::MessagePumpForUI() - : instance_(NULL), - message_filter_(new MessageFilter) { - InitMessageWnd(); + : message_filter_(new MessageFilter), + window_(new win::MessageWindow()) { + CHECK(window_->Create(this)); } MessagePumpForUI::~MessagePumpForUI() { - DestroyWindow(message_hwnd_); - UnregisterClass(kWndClass, instance_); } void MessagePumpForUI::ScheduleWork() { @@ -111,8 +108,7 @@ void MessagePumpForUI::ScheduleWork() { return; // Someone else continued the pumping. // Make sure the MessagePump does some work for us. - BOOL ret = PostMessage(message_hwnd_, kMsgHaveWork, - reinterpret_cast<WPARAM>(this), 0); + BOOL ret = PostMessage(window_->hwnd(), kMsgHaveWork, 0, 0); if (ret) return; // There was room in the Window Message queue. @@ -159,8 +155,7 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { // Create a WM_TIMER event that will wake us up to check for any pending // timers (in case we are running within a nested, external sub-pump). - BOOL ret = SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), - delay_msec, NULL); + BOOL ret = SetTimer(window_->hwnd(), kTimerId, delay_msec, NULL); if (ret) return; // If we can't set timers, we are in big trouble... but cross our fingers for @@ -197,18 +192,23 @@ void MessagePumpForUI::PumpOutPendingPaintMessages() { //----------------------------------------------------------------------------- // MessagePumpForUI private: -// static -LRESULT CALLBACK MessagePumpForUI::WndProcThunk( - HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { +bool MessagePumpForUI::HandleMessage(HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam, + LRESULT* result) { switch (message) { case kMsgHaveWork: - reinterpret_cast<MessagePumpForUI*>(wparam)->HandleWorkMessage(); + HandleWorkMessage(); break; + case WM_TIMER: - reinterpret_cast<MessagePumpForUI*>(wparam)->HandleTimerMessage(); + HandleTimerMessage(); break; } - return DefWindowProc(hwnd, message, wparam, lparam); + + // Do default processing for all messages. + return false; } void MessagePumpForUI::DoRunLoop() { @@ -249,7 +249,7 @@ void MessagePumpForUI::DoRunLoop() { // don't want to disturb that timer if it is already in flight. However, // if we did do all remaining delayed work, then lets kill the WM_TIMER. if (more_work_is_plausible && delayed_work_time_.is_null()) - KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); + KillTimer(window_->hwnd(), kTimerId); if (state_->should_quit) break; @@ -267,20 +267,6 @@ void MessagePumpForUI::DoRunLoop() { } } -void MessagePumpForUI::InitMessageWnd() { - WNDCLASSEX wc = {0}; - wc.cbSize = sizeof(wc); - wc.lpfnWndProc = base::win::WrappedWindowProc<WndProcThunk>; - wc.hInstance = base::GetModuleFromAddress(wc.lpfnWndProc); - wc.lpszClassName = kWndClass; - instance_ = wc.hInstance; - RegisterClassEx(&wc); - - message_hwnd_ = - CreateWindow(kWndClass, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, instance_, 0); - DCHECK(message_hwnd_); -} - void MessagePumpForUI::WaitForWork() { // Wait until a message is available, up to the time needed by the timer // manager to fire the next set of timers. @@ -338,7 +324,7 @@ void MessagePumpForUI::HandleWorkMessage() { } void MessagePumpForUI::HandleTimerMessage() { - KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this)); + KillTimer(window_->hwnd(), kTimerId); // If we are being called outside of the context of Run, then don't do // anything. This could correspond to a MessageBox call or something of @@ -382,7 +368,7 @@ bool MessagePumpForUI::ProcessMessageHelper(const MSG& msg) { } // While running our main message pump, we discard kMsgHaveWork messages. - if (msg.message == kMsgHaveWork && msg.hwnd == message_hwnd_) + if (msg.message == kMsgHaveWork && msg.hwnd == window_->hwnd()) return ProcessPumpReplacementMessage(); if (CallMsgFilter(const_cast<MSG*>(&msg), kMessageFilterCode)) @@ -429,7 +415,7 @@ bool MessagePumpForUI::ProcessPumpReplacementMessage() { } DCHECK(!have_message || kMsgHaveWork != msg.message || - msg.hwnd != message_hwnd_); + msg.hwnd != window_->hwnd()); // Since we discarded a kMsgHaveWork message, we must update the flag. int old_have_work = InterlockedExchange(&have_work_, 0); |