Take 2 at the new MessageLoop implementation.

R=jar



git-svn-id: svn://svn.chromium.org/chrome/trunk/src@973 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: fc7fb6e30c5c3574dfade2803f1793b9110d1370
diff --git a/base/message_loop.cc b/base/message_loop.cc
index 18f4448..4d61b6a 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -27,14 +27,13 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#include <algorithm>
-
 #include "base/message_loop.h"
 
+#include <algorithm>
+
 #include "base/logging.h"
 #include "base/string_util.h"
 #include "base/thread_local_storage.h"
-#include "base/win_util.h"
 
 // a TLS index to the message loop for the current thread
 // Note that if we start doing complex stuff in other static initializers
@@ -43,25 +42,10 @@
 
 //------------------------------------------------------------------------------
 
-static const wchar_t kWndClass[] = L"Chrome_MessageLoopWindow";
-
-// Windows Message numbers handled by WindowMessageProc.
-
-// 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 kMsgPumpATask =        WM_USER + 1;
-
-// Message sent by Quit() to cause our main message pump to terminate as soon as
-// all pending task and message queues have been emptied.
-static const int kMsgQuit =             WM_USER + 2;
-
 // Logical events for Histogram profiling. Run with -message-loop-histogrammer
 // to get an accounting of messages and actions taken on each thread.
-static const int kTaskRunEvent =        WM_USER + 16;  // 0x411
-static const int kSleepingApcEvent =    WM_USER + 17;  // 0x411
-static const int kPollingSignalEvent =  WM_USER + 18;  // 0x412
-static const int kSleepingSignalEvent = WM_USER + 19;  // 0x413
-static const int kTimerEvent =          WM_USER + 20;  // 0x414
+static const int kTaskRunEvent = 0x1;
+static const int kTimerEvent = 0x2;
 
 // Provide range of message IDs for use in histogramming and debug display.
 static const int kLeastNonZeroMessageId = 1;
@@ -70,26 +54,8 @@
 
 //------------------------------------------------------------------------------
 
-#ifndef NDEBUG
-// Force exercise of polling model.
-#define CHROME_MAXIMUM_WAIT_OBJECTS 8
-#else
-#define CHROME_MAXIMUM_WAIT_OBJECTS MAXIMUM_WAIT_OBJECTS
-#endif
+#if defined(OS_WIN)
 
-//------------------------------------------------------------------------------
-// A strategy of -1 uses the default case. All strategies are selected as
-// positive integers.
-// static
-int MessageLoop::strategy_selector_ = -1;
-
-// static
-void MessageLoop::SetStrategy(int strategy) {
-  DCHECK(-1 == strategy_selector_);
-  strategy_selector_ = strategy;
-}
-
-//------------------------------------------------------------------------------
 // Upon a SEH exception in this thread, it restores the original unhandled
 // exception filter.
 static int SEHFilter(LPTOP_LEVEL_EXCEPTION_FILTER old_filter) {
@@ -106,23 +72,22 @@
   return top_filter;
 }
 
+#endif  // defined(OS_WIN)
+
 //------------------------------------------------------------------------------
 
 MessageLoop::MessageLoop()
 #pragma warning(suppress: 4355)  // OK, to use |this| in the initializer list.
     : timer_manager_(this),
-      message_hwnd_(NULL),
       exception_restoration_(false),
       nestable_tasks_allowed_(true),
-      dispatcher_(NULL),
-      quit_received_(false),
-      quit_now_(false),
-      task_pump_message_pending_(false),
-      run_depth_(0) {
+      state_(NULL) {
   DCHECK(tls_index_) << "static initializer failed";
   DCHECK(!current()) << "should only have one message loop per thread";
   ThreadLocalStorage::Set(tls_index_, this);
-  InitMessageWnd();
+#if defined(OS_WIN)
+  pump_ = new base::MessagePumpWin();
+#endif
 }
 
 MessageLoop::~MessageLoop() {
@@ -135,8 +100,7 @@
   // OK, now make it so that no one can find us.
   ThreadLocalStorage::Set(tls_index_, NULL);
 
-  DCHECK(!dispatcher_);
-  DCHECK(!quit_received_ && !quit_now_);
+  DCHECK(!state_);
 
   // Most tasks that have not been Run() are deleted in the |timer_manager_|
   // destructor after we remove our tls index.  We delete the tasks in our
@@ -147,12 +111,6 @@
   DeletePendingTasks();
 }
 
-void MessageLoop::SetThreadName(const std::string& thread_name) {
-  DCHECK(thread_name_.empty());
-  thread_name_ = thread_name;
-  StartHistogrammer();
-}
-
 void MessageLoop::AddDestructionObserver(DestructionObserver *obs) {
   DCHECK(this == current());
   destruction_observers_.AddObserver(obs);
@@ -163,26 +121,23 @@
   destruction_observers_.RemoveObserver(obs);
 }
 
-void MessageLoop::AddObserver(Observer *obs) {
-  DCHECK(this == current());
-  observers_.AddObserver(obs);
-}
-
-void MessageLoop::RemoveObserver(Observer *obs) {
-  DCHECK(this == current());
-  observers_.RemoveObserver(obs);
-}
-
 void MessageLoop::Run() {
-  RunHandler(NULL, false);
+  AutoRunState save_state(this);
+  RunHandler();
 }
 
-void MessageLoop::Run(Dispatcher* dispatcher) {
-  RunHandler(dispatcher, false);
+#if defined(OS_WIN)
+void MessageLoop::Run(base::MessagePumpWin::Dispatcher* dispatcher) {
+  AutoRunState save_state(this);
+  state_->dispatcher = dispatcher;
+  RunHandler();
 }
+#endif
 
 void MessageLoop::RunAllPending() {
-  RunHandler(NULL, true);
+  AutoRunState save_state(this);
+  state_->quit_received = true;  // Means run until we would otherwise block.
+  RunHandler();
 }
 
 // Runs the loop in two different SEH modes:
@@ -190,94 +145,43 @@
 // one that calls SetUnhandledExceptionFilter().
 // enable_SEH_restoration_ = true : any unhandled exception goes to the filter
 // that was existed before the loop was run.
-void MessageLoop::RunHandler(Dispatcher* dispatcher, bool non_blocking) {
+void MessageLoop::RunHandler() {
+#if defined(OS_WIN)
   if (exception_restoration_) {
     LPTOP_LEVEL_EXCEPTION_FILTER current_filter = GetTopSEHFilter();
     __try {
-      RunInternal(dispatcher, non_blocking);
+      RunInternal();
     } __except(SEHFilter(current_filter)) {
     }
-  } else {
-    RunInternal(dispatcher, non_blocking);
+    return;
   }
+#endif
+
+  RunInternal();
 }
 
 //------------------------------------------------------------------------------
-// IF this was just a simple PeekMessage() loop (servicing all passible work
-// queues), then Windows would try to achieve the following order according to
-// MSDN documentation about PeekMessage with no filter):
-//    * Sent messages
-//    * Posted messages
-//    * Sent messages (again)
-//    * WM_PAINT messages
-//    * WM_TIMER messages
-//
-// Summary: none of the above classes is starved, and sent messages has twice
-// the chance of being processed (i.e., reduced service time).
 
-void MessageLoop::RunInternal(Dispatcher* dispatcher, bool non_blocking) {
-  // Preserve ability to be called recursively.
-  ScopedStateSave save(this);  // State is restored on exit.
-  dispatcher_ = dispatcher;
+void MessageLoop::RunInternal() {
+  DCHECK(this == current());
+
   StartHistogrammer();
 
-  DCHECK(this == current());
-  //
-  // Process pending messages and signaled objects.
-  //
-  // Flush these queues before exiting due to a kMsgQuit or else we risk not
-  // shutting down properly as some operations may depend on further event
-  // processing. (Note: some tests may use quit_now_ to exit more swiftly,
-  // and leave messages pending, so don't assert the above fact).
-  RunTraditional(non_blocking);
-  DCHECK(non_blocking || quit_received_ || quit_now_);
-}
-
-void MessageLoop::RunTraditional(bool non_blocking) {
-  for (;;) {
-    // If we do any work, we may create more messages etc., and more work
-    // may possibly be waiting in another task group.  When we (for example)
-    // ProcessNextWindowsMessage(), there is a good chance there are still more
-    // messages waiting (same thing for ProcessNextObject(), which responds to
-    // only one signaled object; etc.).  On the other hand, when any of these
-    // methods return having done no work, then it is pretty unlikely that
-    // calling them again quickly will find any work to do.
-    // Finally, if they all say they had no work, then it is a good time to
-    // consider sleeping (waiting) for more work.
-    bool more_work_is_plausible = ProcessNextWindowsMessage();
-    if (quit_now_)
-      return;
-
-    more_work_is_plausible |= ProcessNextDeferredTask();
-    more_work_is_plausible |= ProcessNextObject();
-    if (more_work_is_plausible)
-      continue;
-
-    if (quit_received_)
-      return;
-
-    // Run any timer that is ready to run. It may create messages etc.
-    if (ProcessSomeTimers())
-      continue;
-
-    // We run delayed non nestable tasks only after all nestable tasks have
-    // run, to preserve FIFO ordering.
-    if (ProcessNextDelayedNonNestableTask())
-      continue;
-
-    if (non_blocking)
-      return;
-
-    // We service APCs in WaitForWork, without returning.
-    WaitForWork();  // Wait (sleep) until we have work to do again.
+#if defined(OS_WIN)
+  if (state_->dispatcher) {
+    pump_win()->RunWithDispatcher(this, state_->dispatcher);
+    return;
   }
+#endif
+  
+  pump_->Run(this);
 }
 
 //------------------------------------------------------------------------------
 // Wrapper functions for use in above message loop framework.
 
 bool MessageLoop::ProcessNextDelayedNonNestableTask() {
-  if (run_depth_ != 1)
+  if (state_->run_depth != 1)
     return false;
 
   if (delayed_non_nestable_queue_.Empty())
@@ -287,53 +191,15 @@
   return true;
 }
 
-bool MessageLoop::ProcessNextDeferredTask() {
-  ReloadWorkQueue();
-  return QueueOrRunTask(NULL);
-}
-
-bool MessageLoop::ProcessSomeTimers() {
-  return timer_manager_.RunSomePendingTimers();
-}
-
 //------------------------------------------------------------------------------
 
 void MessageLoop::Quit() {
-  EnsureMessageGetsPosted(kMsgQuit);
-}
-
-bool MessageLoop::WatchObject(HANDLE object, Watcher* watcher) {
-  DCHECK(this == current());
-  DCHECK(object);
-  DCHECK_NE(object, INVALID_HANDLE_VALUE);
-
-  std::vector<HANDLE>::iterator it = find(objects_.begin(), objects_.end(),
-                                          object);
-  if (watcher) {
-    if (it == objects_.end()) {
-     static size_t warning_multiple = 1;
-     if (objects_.size() >= warning_multiple * MAXIMUM_WAIT_OBJECTS / 2) {
-       LOG(INFO) << "More than " << warning_multiple * MAXIMUM_WAIT_OBJECTS / 2
-           << " objects being watched";
-       // This DCHECK() is an artificial limitation, meant to warn us if we
-       // start creating too many objects.  It can safely be raised to a higher
-       // level, and the program is designed to handle much larger values.
-       // Before raising this limit, make sure that there is a very good reason
-       // (in your debug testing) to be watching this many objects.
-       DCHECK(2 <= warning_multiple);
-       ++warning_multiple;
-      }
-      objects_.push_back(object);
-      watchers_.push_back(watcher);
-    } else {
-      watchers_[it - objects_.begin()] = watcher;
-    }
-  } else if (it != objects_.end()) {
-    std::vector<HANDLE>::difference_type index = it - objects_.begin();
-    objects_.erase(it);
-    watchers_.erase(watchers_.begin() + index);
+  DCHECK(current() == this);
+  if (state_) {
+    state_->quit_received = true;
+  } else {
+    NOTREACHED() << "Must be inside Run to call Quit";
   }
-  return true;
 }
 
 // Possibly called on a background thread!
@@ -352,88 +218,23 @@
   // directly, as it could starve handling of foreign threads.  Put every task
   // into this queue.
 
-  // Local stack variables to use IF we need to process after releasing locks.
-  HWND message_hwnd;
+  scoped_refptr<base::MessagePump> pump;
   {
-    AutoLock lock1(incoming_queue_lock_);
+    AutoLock locked(incoming_queue_lock_);
+
     bool was_empty = incoming_queue_.Empty();
     incoming_queue_.Push(task);
     if (!was_empty)
       return;  // Someone else should have started the sub-pump.
 
-    // We may have to start the sub-pump.
-    AutoLock lock2(task_pump_message_lock_);
-    if (task_pump_message_pending_)
-      return;  // Someone else continued the pumping.
-    task_pump_message_pending_ = true;  // We'll send one.
-    message_hwnd = message_hwnd_;
-  }  // Release both locks.
-  // We may have just posted a kMsgQuit, and so this instance may now destroyed!
-  // Do not invoke non-static methods, or members in any way!
-
-  // PostMessage may fail, as the hwnd may have vanished due to kMsgQuit.
-  PostMessage(message_hwnd, kMsgPumpATask, 0, 0);
-}
-
-void MessageLoop::InitMessageWnd() {
-  HINSTANCE hinst = GetModuleHandle(NULL);
-
-  WNDCLASSEX wc = {0};
-  wc.cbSize = sizeof(wc);
-  wc.lpfnWndProc = WndProcThunk;
-  wc.hInstance = hinst;
-  wc.lpszClassName = kWndClass;
-  RegisterClassEx(&wc);
-
-  message_hwnd_ = CreateWindow(kWndClass, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0,
-                               hinst, 0);
-  DCHECK(message_hwnd_);
-}
-
-// static
-LRESULT CALLBACK MessageLoop::WndProcThunk(
-    HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
-  DCHECK(MessageLoop::current());
-  return MessageLoop::current()->WndProc(hwnd, message, wparam, lparam);
-}
-
-LRESULT MessageLoop::WndProc(
-    HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
-  if (hwnd == message_hwnd_) {
-    switch (message) {
-      case kMsgPumpATask: {
-        ProcessPumpReplacementMessage();  // Avoid starving paint and timer.
-        if (!nestable_tasks_allowed_)
-          return 0;
-        PumpATaskDuringWndProc();
-        return 0;
-      }
-
-      case WM_TIMER:
-        ProcessSomeTimers();         // Give the TimerManager a tickle.
-        DidChangeNextTimerExpiry();  // Maybe generate another WM_TIMER.
-        return 0;
-
-      case kMsgQuit: {
-        // TODO(jar): bug 1300541 The following assert should be used, but
-        // currently too much code actually triggers the assert, especially in
-        // tests :-(.
-        // Discarding a second quit will cause a hang.
-        //CHECK(!quit_received_);
-        quit_received_ = true;
-        return 0;
-      }
-    }
+    pump = pump_;
   }
-  return ::DefWindowProc(hwnd, message, wparam, lparam);
-}
+  // Since the incoming_queue_ may contain a task that destroys this message
+  // loop, we cannot exit incoming_queue_lock_ until we are done with |this|.
+  // We use a stack-based reference to the message pump so that we can call
+  // ScheduleWork outside of incoming_queue_lock_.
 
-void MessageLoop::WillProcessMessage(const MSG& msg) {
-  FOR_EACH_OBSERVER(Observer, observers_, WillProcessMessage(msg));
-}
-
-void MessageLoop::DidProcessMessage(const MSG& msg) {
-  FOR_EACH_OBSERVER(Observer, observers_, DidProcessMessage(msg));
+  pump->ScheduleWork();
 }
 
 void MessageLoop::SetNestableTasksAllowed(bool allowed) {
@@ -442,7 +243,7 @@
     if (!nestable_tasks_allowed_)
       return;
     // Start the native pump if we are not already pumping.
-    EnsurePumpATaskWasPosted();
+    pump_->ScheduleWork();
   }
 }
 
@@ -450,215 +251,7 @@
   return nestable_tasks_allowed_;
 }
 
-bool MessageLoop::ProcessNextWindowsMessage() {
-  MSG msg;
-  if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
-    return ProcessMessageHelper(msg);
-  }
-  return false;
-}
-
-bool MessageLoop::ProcessMessageHelper(const MSG& msg) {
-  HistogramEvent(msg.message);
-
-  if (WM_QUIT == msg.message) {
-    // Repost the QUIT message so that it will be retrieved by the primary
-    // GetMessage() loop.
-    quit_now_ = true;
-    PostQuitMessage(static_cast<int>(msg.wParam));
-    return false;
-  }
-
-  // While running our main message pump, we discard kMsgPumpATask messages.
-  if  (msg.message == kMsgPumpATask && msg.hwnd == message_hwnd_)
-    return ProcessPumpReplacementMessage();
-
-  WillProcessMessage(msg);
-
-  if (dispatcher_) {
-    if (!dispatcher_->Dispatch(msg))
-      quit_now_ = true;
-  } else {
-    TranslateMessage(&msg);
-    DispatchMessage(&msg);
-  }
-
-  DidProcessMessage(msg);
-  return true;
-}
-
-bool MessageLoop::ProcessPumpReplacementMessage() {
-  MSG msg;
-  bool have_message = (0 != PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
-  DCHECK(!have_message || kMsgPumpATask != msg.message
-         || msg.hwnd != message_hwnd_);
-  {
-    // Since we discarded a kMsgPumpATask message, we must update the flag.
-    AutoLock lock(task_pump_message_lock_);
-    DCHECK(task_pump_message_pending_);
-    task_pump_message_pending_ = false;
-  }
-  return have_message && ProcessMessageHelper(msg);
-}
-
-// Create a mini-message-pump to force immediate processing of only Windows
-// WM_PAINT messages.
-void MessageLoop::PumpOutPendingPaintMessages() {
-  // Don't provide an infinite loop, but do enough peeking to get the job done.
-  // Actual common max is 4 peeks, but we'll be a little safe here.
-  const int kMaxPeekCount = 20;
-  int peek_count;
-  bool win2k(true);
-  if (win_util::GetWinVersion() > win_util::WINVERSION_2000)
-    win2k = false;
-  for (peek_count = 0; peek_count < kMaxPeekCount; ++peek_count) {
-    MSG msg;
-    if (win2k) {
-      if (!PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_REMOVE))
-        break;
-    } else {
-      if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE | PM_QS_PAINT))
-        break;
-    }
-    ProcessMessageHelper(msg);
-    if (quit_now_ )  // Handle WM_QUIT.
-      break;
-  }
-  // Histogram what was really being used, to help to adjust kMaxPeekCount.
-  DHISTOGRAM_COUNTS(L"Loop.PumpOutPendingPaintMessages Peeks", peek_count);
-}
-
 //------------------------------------------------------------------------------
-// If we handle more than the OS limit on the number of objects that can be
-// waited for, we'll need to poll (sequencing through subsets of the objects
-// that can be passed in a single OS wait call).  The following is the polling
-// interval used in that (unusual) case. (I don't have a lot of justifcation
-// for the specific value, but it needed to be short enough that it would not
-// add a lot of latency, and long enough that we wouldn't thrash the CPU for no
-// reason... especially considering the silly user probably has a million tabs
-// open, etc.)
-static const int kMultipleWaitPollingInterval = 20;
-
-void MessageLoop::WaitForWork() {
-  bool original_can_run = nestable_tasks_allowed_;
-  int wait_flags = original_can_run ? MWMO_ALERTABLE | MWMO_INPUTAVAILABLE
-                                    : MWMO_INPUTAVAILABLE;
-
-  bool use_polling = false;  // Poll if too many objects for one OS Wait call.
-  for (;;) {
-    // Do initialization here, in case APC modifies object list.
-    size_t total_objs = original_can_run ? objects_.size() : 0;
-
-    int delay;
-    size_t polling_index = 0;  // The first unprocessed object index.
-    do {
-      size_t objs_len =
-          (polling_index < total_objs) ? total_objs - polling_index : 0;
-      if (objs_len >= CHROME_MAXIMUM_WAIT_OBJECTS) {
-        objs_len = CHROME_MAXIMUM_WAIT_OBJECTS - 1;
-        use_polling = true;
-      }
-      HANDLE* objs = objs_len ? polling_index + &objects_.front() : NULL;
-
-      // Only wait up to the time needed by the timer manager to fire the next
-      // set of timers.
-      delay = timer_manager_.GetCurrentDelay();
-      if (use_polling && delay > kMultipleWaitPollingInterval)
-        delay = kMultipleWaitPollingInterval;
-      if (delay < 0)  // Negative value means no timers waiting.
-        delay = INFINITE;
-
-      DWORD result;
-      result = MsgWaitForMultipleObjectsEx(static_cast<DWORD>(objs_len), objs,
-                                           delay, QS_ALLINPUT, wait_flags);
-
-      if (WAIT_IO_COMPLETION == result) {
-        HistogramEvent(kSleepingApcEvent);
-        // We'll loop here when we service an APC.  At it currently stands,
-        // *ONLY* the IO thread uses *any* APCs, so this should have no impact
-        // on the UI thread.
-        break;  // Break to outer loop, and waitforwork() again.
-      }
-
-      // Use unsigned type to simplify range detection;
-      size_t signaled_index = result - WAIT_OBJECT_0;
-      if (signaled_index < objs_len) {
-        SignalWatcher(polling_index + signaled_index);
-        HistogramEvent(kSleepingSignalEvent);
-        return;  // We serviced a signaled object.
-      }
-
-      if (objs_len == signaled_index)
-        return;  // A WM_* message is available.
-
-      DCHECK_NE(WAIT_FAILED, result) << GetLastError();
-
-      DCHECK(!objs || result == WAIT_TIMEOUT);
-      if (!use_polling)
-        return;
-      polling_index += objs_len;
-    } while (polling_index < total_objs);
-    // For compatibility, we didn't return sooner.  This made us do *some* wait
-    // call(s) before returning. This will probably change in next rev.
-    if (!delay || !timer_manager_.GetCurrentDelay())
-      return;  // No work done, but timer is ready to fire.
-  }
-}
-
-// Note: MsgWaitMultipleObjects() can't take a nil list, and that is why I had
-// to use SleepEx() to handle APCs when there were no objects.
-bool MessageLoop::ProcessNextObject() {
-  if (!nestable_tasks_allowed_)
-    return false;
-
-  size_t total_objs = objects_.size();
-  if (!total_objs) {
-    return false;
-  }
-
-  size_t polling_index = 0;  // The first unprocessed object index.
-  do {
-    DCHECK(polling_index < total_objs);
-    size_t objs_len = total_objs - polling_index;
-    if (objs_len >= CHROME_MAXIMUM_WAIT_OBJECTS)
-      objs_len = CHROME_MAXIMUM_WAIT_OBJECTS - 1;
-    HANDLE* objs = polling_index + &objects_.front();
-
-    // Identify 1 pending object, or allow an IO APC to be completed.
-    DWORD result = WaitForMultipleObjectsEx(static_cast<DWORD>(objs_len), objs,
-                                            FALSE,    // 1 signal is sufficient.
-                                            0,        // Wait 0ms.
-                                            false);  // Not alertable (no APC).
-
-    // Use unsigned type to simplify range detection;
-    size_t signaled_index = result - WAIT_OBJECT_0;
-    if (signaled_index < objs_len) {
-      SignalWatcher(polling_index + signaled_index);
-      HistogramEvent(kPollingSignalEvent);
-      return true;  // We serviced a signaled object.
-    }
-
-    // If an handle is invalid, it will be WAIT_FAILED.
-    DCHECK_EQ(WAIT_TIMEOUT, result) << GetLastError();
-    polling_index += objs_len;
-  } while (polling_index < total_objs);
-  return false;  // We serviced nothing.
-}
-
-bool MessageLoop::SignalWatcher(size_t object_index) {
-  BeforeTaskRunSetup();
-  DCHECK(objects_.size() > object_index);
-  // On reception of OnObjectSignaled() to a Watcher object, it may call
-  // WatchObject(). watchers_ and objects_ will be modified. This is
-  // expected, so don't be afraid if, while tracing a OnObjectSignaled()
-  // function, the corresponding watchers_[result] is inexistant.
-  watchers_[object_index]->OnObjectSignaled(objects_[object_index]);
-  // Signaled objects tend to be removed from the watch list, and then added
-  // back (appended).  As a result, they move to the end of the objects_ array,
-  // and this should make their service "fair" (no HANDLEs should be starved).
-  AfterTaskRunRestore();
-  return true;
-}
 
 bool MessageLoop::RunTimerTask(Timer* timer) {
   HistogramEvent(kTimerEvent);
@@ -705,16 +298,15 @@
   // Execute oldest task.
   while (!work_queue_.Empty()) {
     Task* task = work_queue_.Pop();
-    if (task->nestable() || run_depth_ == 1) {
+    if (task->nestable() || state_->run_depth == 1) {
       RunTask(task);
       // Show that we ran a task (Note: a new one might arrive as a
       // consequence!).
       return true;
-    } else {
-      // We couldn't run the task now because we're in a nested message loop
-      // and the task isn't nestable.
-      delayed_non_nestable_queue_.Push(task);
     }
+    // We couldn't run the task now because we're in a nested message loop
+    // and the task isn't nestable.
+    delayed_non_nestable_queue_.Push(task);
   }
 
   // Nothing happened.
@@ -743,54 +335,12 @@
   nestable_tasks_allowed_ = true;
 }
 
-void MessageLoop::PumpATaskDuringWndProc() {
-  // TODO(jar): Perchance we should check on signaled objects here??
-  // Signals are generally starved during a native message loop.  Even if we
-  // try to service a signaled object now, we wouldn't automatically get here
-  // (i.e., the native pump would not re-start) when the next object was
-  // signaled. If we really want to avoid starving signaled objects, we need
-  // to translate them into Tasks that can be passed in via PostTask.
-  // If these native message loops (and sub-pumping activities) are short
-  // lived, then the starvation won't be that long :-/.
-
-  if (!ProcessNextDeferredTask())
-    return;  // Nothing to do, so lets stop the sub-pump.
-
-  // We ran a task, so make sure we come back and try to run more tasks.
-  EnsurePumpATaskWasPosted();
-}
-
-void MessageLoop::EnsurePumpATaskWasPosted() {
-  {
-    AutoLock lock(task_pump_message_lock_);
-    if (task_pump_message_pending_)
-      return;  // Someone else continued the pumping.
-    task_pump_message_pending_ = true;  // We'll send one.
-  }
-  EnsureMessageGetsPosted(kMsgPumpATask);
-}
-
-void MessageLoop::EnsureMessageGetsPosted(int message) const {
-  const int kRetryCount = 30;
-  const int kSleepDurationWhenFailing = 100;
-  for (int i = 0; i < kRetryCount; ++i) {
-    // Posting to our own windows should always succeed.  If it doesn't we're in
-    // big trouble.
-    if (PostMessage(message_hwnd_, message, 0, 0))
-      return;
-    Sleep(kSleepDurationWhenFailing);
-  }
-  LOG(FATAL) << "Crash with last error " << GetLastError();
-  int* p = NULL;
-  *p = 0;  // Crash.
-}
-
 void MessageLoop::ReloadWorkQueue() {
   // We can improve performance of our loading tasks from incoming_queue_ to
-  // work_queue_ by wating until the last minute (work_queue_ is empty) to load.
-  // That reduces the number of locks-per-task significantly when our queues get
-  // large.  The optimization is disabled on threads that make use of the
-  // priority queue (prioritization requires all our tasks to be in the
+  // work_queue_ by waiting until the last minute (work_queue_ is empty) to
+  // load.  That reduces the number of locks-per-task significantly when our
+  // queues get large.  The optimization is disabled on threads that make use
+  // of the priority queue (prioritization requires all our tasks to be in the
   // work_queue_ ASAP).
   if (!work_queue_.Empty() && !work_queue_.use_priority_queue())
     return;  // Wait till we *really* need to lock and load.
@@ -833,42 +383,65 @@
 }
 
 void MessageLoop::DidChangeNextTimerExpiry() {
-#if defined(OS_WIN)
-  //
-  // We would *like* to provide high resolution timers.  Windows timers using
-  // SetTimer() have a 10ms granularity.  We have to use WM_TIMER as a wakeup
-  // mechanism because the application can enter modal windows loops where it
-  // is not running our MessageLoop; the only way to have our timers fire in
-  // these cases is to post messages there.
-  //
-  // To provide sub-10ms timers, we process timers directly from our run loop.
-  // For the common case, timers will be processed there as the run loop does
-  // its normal work.  However, we *also* set the system timer so that WM_TIMER
-  // events fire.  This mops up the case of timers not being able to work in
-  // modal message loops.  It is possible for the SetTimer to pop and have no
-  // pending timers, because they could have already been processed by the
-  // run loop itself.
-  //
-  // We use a single SetTimer corresponding to the timer that will expire
-  // soonest.  As new timers are created and destroyed, we update SetTimer.
-  // Getting a spurrious SetTimer event firing is benign, as we'll just be
-  // processing an empty timer queue.
-  //
   int delay = timer_manager_.GetCurrentDelay(); 
-  if (delay == -1) {
-    KillTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this));
+  if (delay == -1)
+    return;
+
+  // Simulates malfunctioning, early firing timers. Pending tasks should only
+  // be invoked when the delay they specify has elapsed.
+  if (timer_manager_.use_broken_delay())
+    delay = 10;
+
+  pump_->ScheduleDelayedWork(TimeDelta::FromMilliseconds(delay));
+}
+
+bool MessageLoop::DoWork() {
+  ReloadWorkQueue();
+  return QueueOrRunTask(NULL);
+}
+
+bool MessageLoop::DoDelayedWork(TimeDelta* next_delay) {
+  bool did_work = timer_manager_.RunSomePendingTimers();
+
+  // We may not have run any timers, but we may still have future timers to
+  // run, so we need to inform the pump again of pending timers.
+  *next_delay = TimeDelta::FromMilliseconds(timer_manager_.GetCurrentDelay());
+
+  return did_work;
+}
+
+bool MessageLoop::DoIdleWork() {
+  if (ProcessNextDelayedNonNestableTask())
+    return true;
+
+  if (state_->quit_received)
+    pump_->Quit();
+
+  return false;
+}
+
+//------------------------------------------------------------------------------
+// MessageLoop::AutoRunState
+
+MessageLoop::AutoRunState::AutoRunState(MessageLoop* loop) : loop_(loop) {
+  // Make the loop reference us.
+  previous_state_ = loop_->state_;
+  if (previous_state_) {
+    run_depth = previous_state_->run_depth + 1;
   } else {
-    if (delay < USER_TIMER_MINIMUM)
-      delay = USER_TIMER_MINIMUM;
-    // Simulates malfunctioning, early firing timers. Pending tasks should only
-    // be invoked when the delay they specify has elapsed.
-    if (timer_manager_.use_broken_delay())
-      delay = 10;
-    // 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).
-    SetTimer(message_hwnd_, reinterpret_cast<UINT_PTR>(this), delay, NULL);
+    run_depth = 1;
   }
-#endif  // defined(OS_WIN)
+  loop_->state_ = this;
+
+  // Initialize the other fields:
+  quit_received = false;
+#if defined(OS_WIN)
+  dispatcher = NULL;
+#endif
+}
+
+MessageLoop::AutoRunState::~AutoRunState() {
+  loop_->state_ = previous_state_;
 }
 
 //------------------------------------------------------------------------------
@@ -963,6 +536,7 @@
 void MessageLoop::StartHistogrammer() {
   if (enable_histogrammer_ && !message_histogram_.get()
       && StatisticsRecorder::WasStarted()) {
+    DCHECK(!thread_name_.empty());
     message_histogram_.reset(new LinearHistogram(
         ASCIIToWide("MsgLoop:" + thread_name_).c_str(),
                     kLeastNonZeroMessageId,
@@ -978,11 +552,6 @@
     message_histogram_->Add(event);
 }
 
-// Add one undocumented windows message to clean up our display.
-#ifndef WM_SYSTIMER
-#define WM_SYSTIMER 0x118
-#endif
-
 // Provide a macro that takes an expression (such as a constant, or macro
 // constant) and creates a pair to initalize an array of pairs.  In this case,
 // our pair consists of the expressions value, and the "stringized" version
@@ -999,33 +568,13 @@
 // in the pair (i.e., the quoted string) when printing out a histogram.
 #define VALUE_TO_NUMBER_AND_NAME(name) {name, #name},
 
-
 // static
 const LinearHistogram::DescriptionPair MessageLoop::event_descriptions_[] = {
-  // Only provide an extensive list in debug mode.  In release mode, we have to
-  // read the octal values.... but we save about 450 strings, each of length
-  // 10 from our binary image.
-#ifndef NDEBUG
-  // Prepare to include a list of names provided in a special header file4.
-#define A_NAMED_MESSAGE_FROM_WINUSER_H VALUE_TO_NUMBER_AND_NAME
-#include "base/windows_message_list.h"
-#undef A_NAMED_MESSAGE_FROM_WINUSER_H
-  // Add an undocumented message that appeared in our list :-/.
-  VALUE_TO_NUMBER_AND_NAME(WM_SYSTIMER)
-#endif  // NDEBUG
-
   // Provide some pretty print capability in our histogram for our internal
   // messages.
 
-  // Values we use for WM_USER+n
-  VALUE_TO_NUMBER_AND_NAME(kMsgPumpATask)
-  VALUE_TO_NUMBER_AND_NAME(kMsgQuit)
-
   // A few events we handle (kindred to messages), and used to profile actions.
   VALUE_TO_NUMBER_AND_NAME(kTaskRunEvent)
-  VALUE_TO_NUMBER_AND_NAME(kSleepingApcEvent)
-  VALUE_TO_NUMBER_AND_NAME(kSleepingSignalEvent)
-  VALUE_TO_NUMBER_AND_NAME(kPollingSignalEvent)
   VALUE_TO_NUMBER_AND_NAME(kTimerEvent)
 
   {-1, NULL}  // The list must be null terminated, per API to histogram.
diff --git a/base/message_loop.h b/base/message_loop.h
index 8ff2c62..afcab64 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -27,8 +27,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifndef BASE_MESSAGE_LOOP_H__
-#define BASE_MESSAGE_LOOP_H__
+#ifndef BASE_MESSAGE_LOOP_H_
+#define BASE_MESSAGE_LOOP_H_
 
 #include <deque>
 #include <queue>
@@ -36,33 +36,39 @@
 #include <vector>
 
 #include "base/histogram.h"
+#include "base/message_pump.h"
 #include "base/observer_list.h"
-#include "base/id_map.h"
+#include "base/ref_counted.h"
 #include "base/task.h"
 #include "base/timer.h"
 #include "base/thread_local_storage.h"
 
-//
-// A MessageLoop is used to process events for a particular thread.
-// There is at most one MessageLoop instance per thread.
-// Events include Windows Message Queue messages, Tasks submitted to PostTask
-// or managed by TimerManager, APC calls (as time permits), and signals sent to
-// a registered set of HANDLES.
-// Processing events corresponds (respectively) to dispatching Windows messages,
-// running Tasks, yielding time to APCs, and calling Watchers when the
-// corresponding HANDLE is signaled.
+#if defined(OS_WIN)
+// We need this to declare base::MessagePumpWin::Dispatcher, which we should
+// really just eliminate.
+#include "base/message_pump_win.h"
+#endif
 
+// A MessageLoop is used to process events for a particular thread.  There is
+// at most one MessageLoop instance per thread.
+//
+// Events include at a minimum Task instances submitted to PostTask or those
+// managed by TimerManager.  Depending on the type of message pump used by the
+// MessageLoop other events such as UI messages may be processed.  On Windows
+// APC calls (as time permits) and signals sent to a registered set of HANDLEs
+// may also be processed.
 //
 // NOTE: Unless otherwise specified, a MessageLoop's methods may only be called
 // on the thread where the MessageLoop's Run method executes.
 //
-// WARNING: MessageLoop has task reentrancy protection. This means that if a
+// NOTE: MessageLoop has task reentrancy protection.  This means that if a
 // task is being processed, a second task cannot start until the first task is
-// finished. Reentrancy can happen when processing a task, and an inner message
-// pump is created.  That inner pump then processes windows messages which could
-// implicitly start an inner task. Inner messages pumps are created with dialogs
-// (DialogBox), common dialogs (GetOpenFileName), OLE functions (DoDragDrop),
-// printer functions (StartDoc) and *many* others.
+// finished.  Reentrancy can happen when processing a task, and an inner
+// message pump is created.  That inner pump then processes native messages
+// which could implicitly start an inner task.  Inner message pumps are created
+// with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
+// (DoDragDrop), printer functions (StartDoc) and *many* others.
+//
 // Sample workaround when inner task processing is needed:
 //   bool old_state = MessageLoop::current()->NestableTasksAllowed();
 //   MessageLoop::current()->SetNestableTasksAllowed(true);
@@ -70,142 +76,13 @@
 //   MessageLoop::current()->SetNestableTasksAllowed(old_state);
 //   // Process hr  (the result returned by DoDragDrop().
 //
-// Please be **SURE** your task is reentrant and all global variables are stable
-// and accessible before calling SetNestableTasksAllowed(true).
+// Please be SURE your task is reentrant (nestable) and all global variables
+// are stable and accessible before calling SetNestableTasksAllowed(true).
 //
-
-// Message loop has several distinct functions.  It provides message pumps,
-// responds to windows message dispatches, manipulates queues of Tasks.
-// The most central operation is the implementation of message pumps, along with
-// several subtleties.
-
-// MessageLoop currently implements several different message pumps.  A message
-// pump is (traditionally) something that reads from an incoming queue, and then
-// dispatches the work.
-//
-// The first message pump, RunTraditional(), is among other things a
-// traditional Windows Message pump.  It contains a nearly infinite loop that
-// peeks out messages, and then dispatches them.
-// Intermixed with those peeks are checks on a queue of Tasks, checks for
-// signaled objects, and checks to see if TimerManager has tasks to run.
-// When there are no events to be serviced, this pump goes into a wait state.
-// For 99.99% of all events, this first message pump handles all processing.
-//
-// When a task, or windows event, invokes on the stack a native dialog box or
-// such, that window typically provides a bare bones (native?) message pump.
-// That bare-bones message pump generally supports little more than a peek of
-// the Windows message queue, followed by a dispatch of the peeked message.
-// MessageLoop extends that bare-bones message pump to also service Tasks, at
-// the cost of some complexity.
-// The basic structure of the extension (refered to as a sub-pump) is that a
-// special message,kMsgPumpATask, is repeatedly injected into the Windows
-// Message queue. Each time the kMsgPumpATask message is peeked, checks are made
-// for an extended set of events, including the availability of Tasks to run.
-//
-// After running a task, the special message kMsgPumpATask is again posted to
-// the Windows Message queue, ensuring a future time slice for processing a
-// future event.
-//
-// To prevent flooding the Windows Message queue, care is taken to be sure that
-// at most one kMsgPumpATask message is EVER pending in the Winow's Message
-// queue.
-//
-// There are a few additional complexities in this system where, when there are
-// no Tasks to run, this otherwise infinite stream of messages which drives the
-// sub-pump is halted.  The pump is automatically re-started when Tasks are
-// queued.
-//
-// A second complexity is that the presence of this stream of posted tasks may
-// prevent a bare-bones message pump from ever peeking a WM_PAINT or WM_TIMER.
-// Such paint and timer events always give priority to a posted message, such as
-// kMsgPumpATask messages.  As a result, care is taken to do some peeking in
-// between the posting of each kMsgPumpATask message (i.e., after kMsgPumpATask
-// is peeked, and before a replacement kMsgPumpATask is posted).
-//
-//
-// NOTE: Although it may seem odd that messages are used to start and stop this
-// flow (as opposed to signaling objects, etc.), it should be understood that
-// the native message pump will *only* respond to messages.  As a result, it is
-// an excellent choice.  It is also helpful that the starter messages that are
-// placed in the queue when new task arrive also awakens the RunTraditional()
-// loop.
-
-//------------------------------------------------------------------------------
-class MessageLoop {
+class MessageLoop : public base::MessagePump::Delegate {
  public:
-
-  // Select a non-default strategy for serving pending requests, that is to be
-  // used by all MessageLoop instances.  This is called only once before
-  // constructing any instances.
-  static void SetStrategy(int strategy);
   static void EnableHistogrammer(bool enable_histogrammer);
 
-#ifdef OS_WIN
-  // Used with WatchObject to asynchronously monitor the signaled state of a
-  // HANDLE object.
-  class Watcher {
-   public:
-    virtual ~Watcher() {}
-    // Called from MessageLoop::Run when a signalled object is detected.
-    virtual void OnObjectSignaled(HANDLE object) = 0;
-  };
-
-  // Have the current thread's message loop watch for a signaled object.
-  // Pass a null watcher to stop watching the object.
-  bool WatchObject(HANDLE, Watcher*);
-
-  // An Observer is an object that receives global notifications from the
-  // MessageLoop.
-  //
-  // NOTE: An Observer implementation should be extremely fast!
-  //
-  class Observer {
-   public:
-    virtual ~Observer() {}
-
-    // This method is called before processing a message.
-    // The message may be undefined in which case msg.message is 0
-    virtual void WillProcessMessage(const MSG& msg) = 0;
-
-    // This method is called when control returns from processing a UI message.
-    // The message may be undefined in which case msg.message is 0
-    virtual void DidProcessMessage(const MSG& msg) = 0;
-  };
-
-  // Add an Observer, which will start receiving notifications immediately.
-  void AddObserver(Observer* observer);
-
-  // Remove an Observer.  It is safe to call this method while an Observer is
-  // receiving a notification callback.
-  void RemoveObserver(Observer* observer);
-
-  // Give a chance to code processing additional messages to notify the
-  // message loop observers that another message has been processed.
-  void WillProcessMessage(const MSG& msg);
-  void DidProcessMessage(const MSG& msg);
-
-  // Dispatcher is used during a nested invocation of Run to dispatch events.
-  // If Run is invoked with a non-NULL Dispatcher, MessageLoop does not
-  // dispatch events (or invoke TranslateMessage), rather every message is
-  // passed to Dispatcher's Dispatch method for dispatch. It is up to the
-  // Dispatcher to dispatch, or not, the event.
-  //
-  // The nested loop is exited by either posting a quit, or returning false
-  // from Dispatch.
-  class Dispatcher {
-   public:
-    virtual ~Dispatcher() {}
-    // Dispatches the event. If true is returned processing continues as
-    // normal. If false is returned, the nested loop exits immediately.
-    virtual bool Dispatch(const MSG& msg) = 0;
-  };
-#else  // !OS_WIN
-  // On non-Windows platforms, the Dispatcher does not exist, but we allow the
-  // typename to exist for convenience.  On non-Windows platforms, a Dispatcher
-  // pointer should always be NULL.
-  class Dispatcher;
-#endif  // OS_*
-
   // A DestructionObserver is notified when the current MessageLoop is being
   // destroyed.  These obsevers are notified prior to MessageLoop::current()
   // being changed to return NULL.  This gives interested parties the chance to
@@ -283,19 +160,18 @@
   // Return as soon as all items that can be run are taken care of.
   void RunAllPending();
 
-  // See description of Dispatcher for how Run uses Dispatcher.
-  void Run(Dispatcher* dispatcher);
-
   // Signals the Run method to return after it is done processing all pending
-  // messages.  This method may be called from any thread, but no effort is
-  // made to support concurrent calls to this method from multiple threads.
+  // messages.  This method may only be called on the same thread that called
+  // Run, and Run must still be on the call stack.
   //
-  // For example, the first call to Quit may lead to the MessageLoop being
-  // deleted once its Run method returns, so a second call from another thread
-  // could be problematic.
+  // Use QuitTask if you need to Quit another thread's MessageLoop, but note
+  // that doing so is fairly dangerous if the target thread makes nested calls
+  // to MessageLoop::Run.  The problem being that you won't know which nested
+  // run loop you are quiting, so be careful!
+  //
   void Quit();
 
-  // Invokes Quit on the current MessageLoop when run. Useful to schedule an
+  // Invokes Quit on the current MessageLoop when run.  Useful to schedule an
   // arbitrary MessageLoop to Quit.
   class QuitTask : public Task {
    public:
@@ -310,8 +186,10 @@
   ~MessageLoop();
 
   // Optional call to connect the thread name with this loop.
-  void SetThreadName(const std::string& thread_name);
-  void set_thread_name(const std::string& name) { SetThreadName(name); }
+  void set_thread_name(const std::string& thread_name) {
+    DCHECK(thread_name_.empty()) << "Should not rename this thread!";
+    thread_name_ = thread_name;
+  }
   const std::string& thread_name() const { return thread_name_; }
 
   // Returns the MessageLoop object for the current thread, or null if none.
@@ -348,51 +226,62 @@
     exception_restoration_ = restore;
   }
 
-  // Public entry point for TimerManager to request the Run() of a task.  If we
-  // created the task during an PostTask(FROM_HERE, ), then we will also perform
-  // destructions, and we'll have the option of queueing the task.  If we didn't
-  // create the timer, then we will Run it immediately.
-  bool RunTimerTask(Timer* timer);
+  //----------------------------------------------------------------------------
+#if defined(OS_WIN)
+  // Backwards-compat for the old Windows-specific MessageLoop API.  These APIs
+  // are deprecated.
 
-  // Since some Timer's are owned by MessageLoop, the TimerManager (when it is
-  // being destructed) passses us the timers to discard (without doing a Run()).
-  void DiscardTimer(Timer* timer);
+  typedef base::MessagePumpWin::Dispatcher Dispatcher;
+  typedef base::MessagePumpWin::Observer Observer;
+  typedef base::MessagePumpWin::Watcher Watcher;
 
-  // Applications can call this to encourage us to process all pending WM_PAINT
-  // messages.
-  // This method will process all paint messages the Windows Message queue can
-  // provide, up to some fixed number (to avoid any infinite loops).
-  void PumpOutPendingPaintMessages();
+  void Run(Dispatcher* dispatcher);
+
+  void WatchObject(HANDLE object, Watcher* watcher) {
+    pump_win()->WatchObject(object, watcher);
+  }
+  void AddObserver(Observer* observer) {
+    pump_win()->AddObserver(observer);
+  }
+  void RemoveObserver(Observer* observer) {
+    pump_win()->RemoveObserver(observer);
+  }
+  void WillProcessMessage(const MSG& message) {
+    pump_win()->WillProcessMessage(message);
+  }
+  void DidProcessMessage(const MSG& message) {
+    pump_win()->DidProcessMessage(message);
+  }
+  void PumpOutPendingPaintMessages() {
+    pump_win()->PumpOutPendingPaintMessages();
+  }
+#endif  // defined(OS_WIN)
 
   //----------------------------------------------------------------------------
  private:
   friend class TimerManager;  // So it can call DidChangeNextTimerExpiry
 
-  struct ScopedStateSave {
-    explicit ScopedStateSave(MessageLoop* loop)
-        : loop_(loop),
-          dispatcher_(loop->dispatcher_),
-          quit_now_(loop->quit_now_),
-          quit_received_(loop->quit_received_),
-          run_depth_(loop->run_depth_) {
-      loop->quit_now_ = loop->quit_received_ = false;
-      ++loop->run_depth_;
-    }
+  struct RunState {
+    // Used to count how many Run() invocations are on the stack.
+    int run_depth;
 
-    ~ScopedStateSave() {
-      loop_->run_depth_ = run_depth_;
-      loop_->quit_received_ = quit_received_;
-      loop_->quit_now_ = quit_now_;
-      loop_->dispatcher_ = dispatcher_;
-    }
+    // Used to record that Quit() was called, or that we should quit the pump
+    // once it becomes idle.
+    bool quit_received;
 
+#if defined(OS_WIN)
+    base::MessagePumpWin::Dispatcher* dispatcher;
+#endif
+  };
+
+  class AutoRunState : RunState {
+   public:
+    AutoRunState(MessageLoop* loop);
+    ~AutoRunState();
    private:
     MessageLoop* loop_;
-    Dispatcher* dispatcher_;
-    bool quit_now_;
-    bool quit_received_;
-    int run_depth_;
-  };  // struct ScopedStateSave
+    RunState* previous_state_;
+  };
 
   // A prioritized queue with interface that mostly matches std::queue<>.
   // For debugging/performance testing, you can swap in std::queue<Task*>.
@@ -459,86 +348,36 @@
     DISALLOW_EVIL_CONSTRUCTORS(OptionallyPrioritizedTaskQueue);
   };
 
-#ifdef OS_WIN
-  void InitMessageWnd();
-
-  // Windows procedure for message_hwnd_.
-  static LRESULT CALLBACK WndProcThunk(
-      HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-  LRESULT WndProc(
-      HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
-#endif  // OS_WIN
+#if defined(OS_WIN)
+  base::MessagePumpWin* pump_win() {
+    return static_cast<base::MessagePumpWin*>(pump_.get());
+  }
+#endif
 
   // A function to encapsulate all the exception handling capability in the
-  // stacks around the running of a main message loop.
-  // It will run the message loop in a SEH try block or not depending on the
-  // set_SEH_restoration() flag.
-  void RunHandler(Dispatcher* dispatcher, bool non_blocking);
+  // stacks around the running of a main message loop.  It will run the message
+  // loop in a SEH try block or not depending on the set_SEH_restoration()
+  // flag.
+  void RunHandler();
 
   // A surrounding stack frame around the running of the message loop that
   // supports all saving and restoring of state, as is needed for any/all (ugly)
   // recursive calls.
-  void RunInternal(Dispatcher* dispatcher, bool non_blocking);
+  void RunInternal();
 
-  // An extended message loop (message pump) that loops mostly forever, and
-  // processes task, signals, timers, etc.
-  // If non-blocking is set, it will return rather than wait for new things to
-  // arrive for processing.
-  void RunTraditional(bool non_blocking);
-
-  //----------------------------------------------------------------------------
-  // A list of method wrappers with identical calling signatures (no arguments)
-  // for use in the main message loop.  Method pointers to these methods may be
-  // called round-robin from the main message loop, on any desired schedule.
-
-  bool ProcessNextDeferredTask();
+  // Called to process any delayed non-nestable tasks.
   bool ProcessNextDelayedNonNestableTask();
-  bool ProcessNextObject();
-  bool ProcessSomeTimers();
 
   //----------------------------------------------------------------------------
-  // Process some pending messages.  Returns true if a message was processed.
-  bool ProcessNextWindowsMessage();
-
-  // Wait until either an object is signaled, a message is available, a timer
-  // needs attention, or our incoming_queue_ has gotten a task.
-  // Handle (without returning) any APCs (only IO thread currently has APCs.)
-  void WaitForWork();
-
-#ifdef OS_WIN
-  // Helper function for processing window messages. This includes handling
-  // WM_QUIT, message translation and dispatch, etc.
-  //
-  // If dispatcher_ is non-NULL this method does NOT dispatch the event, instead
-  // it invokes Dispatch on the dispatcher_.
-  bool ProcessMessageHelper(const MSG& msg);
-#endif  // OS_WIN
-
-  // When we encounter a kMsgPumpATask, the following helper can be called to
-  // peek and process a replacement message, such as a WM_PAINT or WM_TIMER.
-  // The goal is to make the kMsgPumpATask as non-intrusive as possible, even
-  // though a continuous stream of such messages are posted.  This method
-  // carefully peeks a message while there is no chance for a kMsgPumpATask to
-  // be pending, then releases the lock (allowing a replacement kMsgPumpATask to
-  // possibly be posted), and finally dispatches that peeked replacement.
-  // Note that the re-post of kMsgPumpATask may be asynchronous to this thread!!
-  bool ProcessPumpReplacementMessage();
-
-  // Signals a watcher if a wait falls within the range of objects we're
-  // waiting on.  object_index is the offset in objects_ that was signaled.
-  // Returns true if an object was signaled.
-  bool SignalWatcher(size_t object_index);
-
   // Run a work_queue_ task or new_task, and delete it (if it was processed by
   // PostTask). If there are queued tasks, the oldest one is executed and
   // new_task is queued. new_task is optional and can be NULL. In this NULL
   // case, the method will run one pending task (if any exist). Returns true if
-  // it executes a task.
-  // Queued tasks accumulate only when there is a nonreentrant task currently
-  // processing, in which case the new_task is appended to the list
-  // work_queue_.  Such re-entrancy generally happens when an unrequested
-  // message pump (typical of a native dialog) is executing in the context of a
-  // task.
+  // it executes a task.  Queued tasks accumulate only when there is a
+  // non-nestable task currently processing, in which case the new_task is
+  // appended to the list work_queue_.  Such re-entrancy generally happens when
+  // an unrequested message pump (typical of a native dialog) is executing in
+  // the context of a task.
   bool QueueOrRunTask(Task* new_task);
 
   // Runs the specified task and deletes it.
@@ -549,14 +388,6 @@
   void BeforeTaskRunSetup();
   void AfterTaskRunRestore();
 
-  // When processing messages in our MessageWndProc(), we are sometimes called
-  // by a native message pump (i.e., We are not called out of our Run() pump).
-  // In those cases, we need to process tasks during the Windows Message
-  // callback.  This method processes a task, and also posts a new kMsgPumpATask
-  // messages to the Windows Msg Queue so that we are called back later (to
-  // process additional tasks).
-  void PumpATaskDuringWndProc();
-
   // Load tasks from the incoming_queue_ into work_queue_ if the latter is
   // empty.  The former requires a lock to access, while the latter is directly
   // accessible on this thread.
@@ -566,19 +397,27 @@
   // destructor to make sure all the task's destructors get called.
   void DeletePendingTasks();
 
-  // Make sure a kPumpATask message is in flight, which starts/continues the
-  // sub-pump.
-  void EnsurePumpATaskWasPosted();
-
-  // Do a PostMessage(), and crash if we can't eventually do the post.
-  void EnsureMessageGetsPosted(int message) const;
-
   // Post a task to our incomming queue.
   void PostTaskInternal(Task* task);
 
   // Called by the TimerManager when its next timer changes.
   void DidChangeNextTimerExpiry();
 
+  // Entry point for TimerManager to request the Run() of a task.  If we
+  // created the task during an PostTask(FROM_HERE, ), then we will also
+  // perform destructions, and we'll have the option of queueing the task.  If
+  // we didn't create the timer, then we will Run it immediately.
+  bool RunTimerTask(Timer* timer);
+
+  // Since some Timer's are owned by MessageLoop, the TimerManager (when it is
+  // being destructed) passses us the timers to discard (without doing a Run()).
+  void DiscardTimer(Timer* timer);
+
+  // base::MessagePump::Delegate methods:
+  virtual bool DoWork();
+  virtual bool DoDelayedWork(TimeDelta* next_delay);
+  virtual bool DoIdleWork();
+
   // Start recording histogram info about events and action IF it was enabled
   // and IF the statistics recorder can accept a registration of our histogram.
   void StartHistogrammer();
@@ -589,7 +428,6 @@
   void HistogramEvent(int event);
 
   static TLSSlot tls_index_;
-  static int strategy_selector_;
   static const LinearHistogram::DescriptionPair event_descriptions_[];
   static bool enable_histogrammer_;
 
@@ -604,29 +442,15 @@
   // there was no real prioritization.
   OptionallyPrioritizedTaskQueue work_queue_;
 
-#ifdef OS_WIN
-  HWND message_hwnd_;
-
-  // A vector of objects (and corresponding watchers) that are routinely
-  // serviced by this message loop's pump.
-  std::vector<HANDLE> objects_;
-  std::vector<Watcher*> watchers_;
-
-  ObserverList<Observer> observers_;
-#endif  // OS_WIN
+  scoped_refptr<base::MessagePump> pump_;
 
   ObserverList<DestructionObserver> destruction_observers_;
-  IDMap<Task> timed_tasks_;
   // A recursion block that prevents accidentally running additonal tasks when
   // insider a (accidentally induced?) nested message pump.
   bool nestable_tasks_allowed_;
 
   bool exception_restoration_;
 
-  Dispatcher* dispatcher_;
-  bool quit_received_;
-  bool quit_now_;
-
   std::string thread_name_;
   // A profiling histogram showing the counts of various messages and events.
   scoped_ptr<LinearHistogram> message_histogram_;
@@ -644,17 +468,9 @@
   // will execute once we're out of nested message loops.
   TaskQueue delayed_non_nestable_queue_;
 
-  // Indicate if there is a kMsgPumpATask message pending in the Windows Message
-  // queue.  There is at most one such message, and it can drive execution of
-  // tasks when a native message pump is running.
-  bool task_pump_message_pending_;
-  // Protect access to task_pump_message_pending_.
-  Lock task_pump_message_lock_;
+  RunState* state_;
 
-  // Used to count how many Run() invocations are on the stack.
-  int run_depth_;
-
-  DISALLOW_EVIL_CONSTRUCTORS(MessageLoop);
+  DISALLOW_COPY_AND_ASSIGN(MessageLoop);
 };
 
-#endif  // BASE_MESSAGE_LOOP_H__
+#endif  // BASE_MESSAGE_LOOP_H_
diff --git a/base/message_pump.h b/base/message_pump.h
index 8e80fc8..90336df 100644
--- a/base/message_pump.h
+++ b/base/message_pump.h
@@ -50,8 +50,11 @@
     // Called from within Run in response to ScheduleDelayedWork or when the
     // message pump would otherwise sleep waiting for more work.  Returns true
     // to indicate that delayed work was done.  DoIdleWork will not be called
-    // if DoDelayedWork returns true.
-    virtual bool DoDelayedWork() = 0;
+    // if DoDelayedWork returns true.  Upon return |next_delay| indicates the
+    // next delayed work interval.  If |next_delay| is negative, then the queue
+    // of future delayed work (timer events) is currently empty, and no
+    // additional calls to this function need to be scheduled.
+    virtual bool DoDelayedWork(TimeDelta* next_delay) = 0;
 
     // Called from within Run just before the message pump goes to sleep.
     // Returns true to indicate that idle work was done.