Fix deadlock that can occur on Windows when shutting down a pool of io_service threads due to running out of work.
diff --git a/asio/include/asio/detail/impl/win_iocp_io_service.ipp b/asio/include/asio/detail/impl/win_iocp_io_service.ipp
index 2580ee2..8f5722c 100644
--- a/asio/include/asio/detail/impl/win_iocp_io_service.ipp
+++ b/asio/include/asio/detail/impl/win_iocp_io_service.ipp
@@ -67,6 +67,7 @@
     iocp_(),
     outstanding_work_(0),
     stopped_(0),
+    stop_event_posted_(0),
     shutdown_(0),
     dispatch_required_(0)
 {
@@ -147,7 +148,7 @@
 {
   if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
   {
-    InterlockedExchange(&stopped_, 1);
+    stop();
     ec = asio::error_code();
     return 0;
   }
@@ -165,7 +166,7 @@
 {
   if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
   {
-    InterlockedExchange(&stopped_, 1);
+    stop();
     ec = asio::error_code();
     return 0;
   }
@@ -179,7 +180,7 @@
 {
   if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
   {
-    InterlockedExchange(&stopped_, 1);
+    stop();
     ec = asio::error_code();
     return 0;
   }
@@ -197,7 +198,7 @@
 {
   if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
   {
-    InterlockedExchange(&stopped_, 1);
+    stop();
     ec = asio::error_code();
     return 0;
   }
@@ -211,12 +212,15 @@
 {
   if (::InterlockedExchange(&stopped_, 1) == 0)
   {
-    if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+    if (::InterlockedExchange(&stop_event_posted_, 1) == 0)
     {
-      DWORD last_error = ::GetLastError();
-      asio::error_code ec(last_error,
-          asio::error::get_system_category());
-      asio::detail::throw_error(ec, "pqcs");
+      if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+      {
+        DWORD last_error = ::GetLastError();
+        asio::error_code ec(last_error,
+            asio::error::get_system_category());
+        asio::detail::throw_error(ec, "pqcs");
+      }
     }
   }
 }
@@ -420,17 +424,23 @@
     }
     else
     {
+      // Indicate that there is no longer an in-flight stop event.
+      ::InterlockedExchange(&stop_event_posted_, 0);
+
       // The stopped_ flag is always checked to ensure that any leftover
-      // interrupts from a previous run invocation are ignored.
+      // stop events from a previous run invocation are ignored.
       if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
       {
         // Wake up next thread that is blocked on GetQueuedCompletionStatus.
-        if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+        if (::InterlockedExchange(&stop_event_posted_, 1) == 0)
         {
-          last_error = ::GetLastError();
-          ec = asio::error_code(last_error,
-              asio::error::get_system_category());
-          return 0;
+          if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+          {
+            last_error = ::GetLastError();
+            ec = asio::error_code(last_error,
+                asio::error::get_system_category());
+            return 0;
+          }
         }
 
         ec = asio::error_code();
diff --git a/asio/include/asio/detail/win_iocp_io_service.hpp b/asio/include/asio/detail/win_iocp_io_service.hpp
index 20bf28f..181df84 100644
--- a/asio/include/asio/detail/win_iocp_io_service.hpp
+++ b/asio/include/asio/detail/win_iocp_io_service.hpp
@@ -236,6 +236,11 @@
   // Flag to indicate whether the event loop has been stopped.
   mutable long stopped_;
 
+  // Flag to indicate whether there is an in-flight stop event. Every event
+  // posted using PostQueuedCompletionStatus consumes non-paged pool, so to
+  // avoid exhausting this resouce we limit the number of outstanding events.
+  long stop_event_posted_;
+
   // Flag to indicate whether the service has been shut down.
   long shutdown_;