Index: base/message_loop/message_pump_win.cc |
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc |
index 36a321092ff21c2f6be12d7fd36f2653e5ddd025..23654946e8555b4d71a9886b4fb432044312d5ea 100644 |
--- a/base/message_loop/message_pump_win.cc |
+++ b/base/message_loop/message_pump_win.cc |
@@ -67,6 +67,10 @@ void MessagePumpWin::RunWithDispatcher( |
state_ = previous_state; |
} |
+void MessagePumpWin::Run(Delegate* delegate) { |
+ RunWithDispatcher(delegate, NULL); |
+} |
+ |
void MessagePumpWin::Quit() { |
DCHECK(state_); |
state_->should_quit = true; |
@@ -103,20 +107,32 @@ MessagePumpForUI::MessagePumpForUI() |
} |
MessagePumpForUI::~MessagePumpForUI() { |
- DestroyWindow(message_hwnd_); |
- UnregisterClass(MAKEINTATOM(atom_), |
- GetModuleFromAddress(&WndProcThunk)); |
+ DCHECK(!atom_); |
+ DCHECK(!message_hwnd_); |
} |
void MessagePumpForUI::ScheduleWork() { |
if (InterlockedExchange(&have_work_, 1)) |
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); |
- if (ret) |
- return; // There was room in the Window Message queue. |
+ // If the attempt to acquire the lock fails, the message loop is shutting down |
+ // and the message window is about to be destroyed as well. |
+ if (!message_hwnd_lock_.Try()) |
+ return; |
+ |
+ { |
+ base::AutoLock lock(message_hwnd_lock_, base::AutoLock::AlreadyAcquired()); |
+ |
+ // Do nothing if the window has been destroyed already. |
+ if (!message_hwnd_) |
+ return; |
+ |
+ // Make sure the MessagePump does some work for us. |
+ if (PostMessage(message_hwnd_, kMsgHaveWork, |
+ reinterpret_cast<WPARAM>(this), 0)) { |
+ return; |
+ } |
+ } |
// We have failed to insert a have-work message, so there is a chance that we |
// will starve tasks/timers while sitting in a nested message loop. Nested |
@@ -172,6 +188,24 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
MESSAGE_LOOP_PROBLEM_MAX); |
} |
+void MessagePumpForUI::Shutdown() { |
+ HWND message_hwnd; |
+ { |
+ base::AutoLock lock(message_hwnd_lock_); |
+ |
+ // Let ScheduleWork() know that the window has been destoyed. |
+ message_hwnd = message_hwnd_; |
+ message_hwnd_ = NULL; |
+ } |
+ |
+ // Destoy the window and its class. The destructor checks whether |
+ // |message_hwnd_| and |atom_| are destroyed, so the variables should be |
+ // cleared here. |
+ DestroyWindow(message_hwnd); |
+ UnregisterClass(MAKEINTATOM(atom_), GetModuleFromAddress(&WndProcThunk)); |
+ atom_ = 0; |
+} |
+ |
void MessagePumpForUI::PumpOutPendingPaintMessages() { |
// If we are being called outside of the context of Run, then don't try to do |
// any work. |
@@ -478,7 +512,7 @@ void MessagePumpForIO::ScheduleWork() { |
return; // Post worked perfectly. |
// See comment in MessagePumpForUI::ScheduleWork() for this error recovery. |
- InterlockedExchange(&have_work_, 0); // Clarify that we didn't succeed. |
+ InterlockedExchange(&have_work_, 0); |
UMA_HISTOGRAM_ENUMERATION("Chrome.MessageLoopProblem", COMPLETION_POST_ERROR, |
MESSAGE_LOOP_PROBLEM_MAX); |
} |
@@ -490,6 +524,9 @@ void MessagePumpForIO::ScheduleDelayedWork(const TimeTicks& delayed_work_time) { |
delayed_work_time_ = delayed_work_time; |
} |
+void MessagePumpForIO::Shutdown() { |
+} |
+ |
void MessagePumpForIO::RegisterIOHandler(HANDLE file_handle, |
IOHandler* handler) { |
ULONG_PTR key = HandlerToKey(handler, true); |