Minimise dependencies on the io_service from the reactors.

Eliminates some circular dependency issues as the system_executor, which
uses the scheduler to implement its post() and defer() functions, is
present everywhere due to associated_executor's primary template.
diff --git a/asio/include/asio/detail/dev_poll_reactor.hpp b/asio/include/asio/detail/dev_poll_reactor.hpp
index 0dab12a..a04463b 100644
--- a/asio/include/asio/detail/dev_poll_reactor.hpp
+++ b/asio/include/asio/detail/dev_poll_reactor.hpp
@@ -33,7 +33,7 @@
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_set.hpp"
 #include "asio/detail/wait_op.hpp"
-#include "asio/io_service.hpp"
+#include "asio/execution_context.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -41,7 +41,7 @@
 namespace detail {
 
 class dev_poll_reactor
-  : public asio::detail::service_base<dev_poll_reactor>
+  : public execution_context_service_base<dev_poll_reactor>
 {
 public:
   enum op_types { read_op = 0, write_op = 1,
@@ -53,7 +53,7 @@
   };
 
   // Constructor.
-  ASIO_DECL dev_poll_reactor(asio::io_service& io_service);
+  ASIO_DECL dev_poll_reactor(asio::execution_context& ctx);
 
   // Destructor.
   ASIO_DECL ~dev_poll_reactor();
@@ -63,7 +63,7 @@
 
   // Recreate internal descriptors following a fork.
   ASIO_DECL void fork_service(
-      asio::io_service::fork_event fork_ev);
+      asio::execution_context::fork_event fork_ev);
 
   // Initialise the task.
   ASIO_DECL void init_task();
@@ -86,7 +86,7 @@
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
-    io_service_.post_immediate_completion(op, is_continuation);
+    scheduler_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
@@ -167,8 +167,8 @@
   // Add a pending event entry for the given descriptor.
   ASIO_DECL ::pollfd& add_pending_event_change(int descriptor);
 
-  // The io_service implementation used to post completions.
-  io_service_impl& io_service_;
+  // The scheduler implementation used to post completions.
+  scheduler& scheduler_;
 
   // Mutex to protect access to internal data.
   asio::detail::mutex mutex_;
diff --git a/asio/include/asio/detail/epoll_reactor.hpp b/asio/include/asio/detail/epoll_reactor.hpp
index 35fb55f..65da611 100644
--- a/asio/include/asio/detail/epoll_reactor.hpp
+++ b/asio/include/asio/detail/epoll_reactor.hpp
@@ -19,7 +19,6 @@
 
 #if defined(ASIO_HAS_EPOLL)
 
-#include "asio/io_service.hpp"
 #include "asio/detail/atomic_count.hpp"
 #include "asio/detail/limits.hpp"
 #include "asio/detail/mutex.hpp"
@@ -31,6 +30,7 @@
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_set.hpp"
 #include "asio/detail/wait_op.hpp"
+#include "asio/execution_context.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -38,7 +38,7 @@
 namespace detail {
 
 class epoll_reactor
-  : public asio::detail::service_base<epoll_reactor>
+  : public execution_context_service_base<epoll_reactor>
 {
 public:
   enum op_types { read_op = 0, write_op = 1,
@@ -72,7 +72,7 @@
   typedef descriptor_state* per_descriptor_data;
 
   // Constructor.
-  ASIO_DECL epoll_reactor(asio::io_service& io_service);
+  ASIO_DECL epoll_reactor(asio::execution_context& ctx);
 
   // Destructor.
   ASIO_DECL ~epoll_reactor();
@@ -82,7 +82,7 @@
 
   // Recreate internal descriptors following a fork.
   ASIO_DECL void fork_service(
-      asio::io_service::fork_event fork_ev);
+      asio::execution_context::fork_event fork_ev);
 
   // Initialise the task.
   ASIO_DECL void init_task();
@@ -106,7 +106,7 @@
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
-    io_service_.post_immediate_completion(op, is_continuation);
+    scheduler_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
@@ -195,8 +195,8 @@
   ASIO_DECL int get_timeout(itimerspec& ts);
 #endif // defined(ASIO_HAS_TIMERFD)
 
-  // The io_service implementation used to post completions.
-  io_service_impl& io_service_;
+  // The scheduler implementation used to post completions.
+  scheduler& scheduler_;
 
   // Mutex to protect access to internal data.
   mutex mutex_;
diff --git a/asio/include/asio/detail/impl/dev_poll_reactor.hpp b/asio/include/asio/detail/impl/dev_poll_reactor.hpp
index f43cab2..d929350 100644
--- a/asio/include/asio/detail/impl/dev_poll_reactor.hpp
+++ b/asio/include/asio/detail/impl/dev_poll_reactor.hpp
@@ -45,12 +45,12 @@
 
   if (shutdown_)
   {
-    io_service_.post_immediate_completion(op, false);
+    scheduler_.post_immediate_completion(op, false);
     return;
   }
 
   bool earliest = queue.enqueue_timer(time, timer, op);
-  io_service_.work_started();
+  scheduler_.work_started();
   if (earliest)
     interrupter_.interrupt();
 }
@@ -64,7 +64,7 @@
   op_queue<operation> ops;
   std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
   lock.unlock();
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
   return n;
 }
 
diff --git a/asio/include/asio/detail/impl/dev_poll_reactor.ipp b/asio/include/asio/detail/impl/dev_poll_reactor.ipp
index 1f365df..3b44d82 100644
--- a/asio/include/asio/detail/impl/dev_poll_reactor.ipp
+++ b/asio/include/asio/detail/impl/dev_poll_reactor.ipp
@@ -29,9 +29,9 @@
 namespace asio {
 namespace detail {
 
-dev_poll_reactor::dev_poll_reactor(asio::io_service& io_service)
-  : asio::detail::service_base<dev_poll_reactor>(io_service),
-    io_service_(use_service<io_service_impl>(io_service)),
+dev_poll_reactor::dev_poll_reactor(asio::execution_context& ctx)
+  : asio::detail::service_base<dev_poll_reactor>(ctx),
+    scheduler_(use_service<scheduler>(ctx)),
     mutex_(),
     dev_poll_fd_(do_dev_poll_create()),
     interrupter_(),
@@ -64,7 +64,7 @@
 
   timer_queues_.get_all_timers(ops);
 
-  io_service_.abandon_operations(ops);
+  scheduler_.abandon_operations(ops);
 } 
 
 // Helper class to re-register all descriptors with /dev/poll.
@@ -88,9 +88,10 @@
   short events_;
 };
 
-void dev_poll_reactor::fork_service(asio::io_service::fork_event fork_ev)
+void dev_poll_reactor::fork_service(
+    asio::execution_context::fork_event fork_ev)
 {
-  if (fork_ev == asio::io_service::fork_child)
+  if (fork_ev == asio::execution_context::fork_child)
   {
     detail::mutex::scoped_lock lock(mutex_);
 
@@ -127,7 +128,7 @@
 
 void dev_poll_reactor::init_task()
 {
-  io_service_.init_task();
+  scheduler_.init_task();
 }
 
 int dev_poll_reactor::register_descriptor(socket_type, per_descriptor_data&)
@@ -182,7 +183,7 @@
         if (op->perform())
         {
           lock.unlock();
-          io_service_.post_immediate_completion(op, is_continuation);
+          scheduler_.post_immediate_completion(op, is_continuation);
           return;
         }
       }
@@ -190,7 +191,7 @@
   }
 
   bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
-  io_service_.work_started();
+  scheduler_.work_started();
   if (first)
   {
     ::pollfd& ev = add_pending_event_change(descriptor);
@@ -410,7 +411,7 @@
   for (int i = 0; i < max_ops; ++i)
     need_interrupt = op_queue_[i].cancel_operations(
         descriptor, ops, ec) || need_interrupt;
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
   if (need_interrupt)
     interrupter_.interrupt();
 }
diff --git a/asio/include/asio/detail/impl/epoll_reactor.hpp b/asio/include/asio/detail/impl/epoll_reactor.hpp
index df60c01..91d85d4 100644
--- a/asio/include/asio/detail/impl/epoll_reactor.hpp
+++ b/asio/include/asio/detail/impl/epoll_reactor.hpp
@@ -43,12 +43,12 @@
 
   if (shutdown_)
   {
-    io_service_.post_immediate_completion(op, false);
+    scheduler_.post_immediate_completion(op, false);
     return;
   }
 
   bool earliest = queue.enqueue_timer(time, timer, op);
-  io_service_.work_started();
+  scheduler_.work_started();
   if (earliest)
     update_timeout();
 }
@@ -62,7 +62,7 @@
   op_queue<operation> ops;
   std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
   lock.unlock();
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
   return n;
 }
 
diff --git a/asio/include/asio/detail/impl/epoll_reactor.ipp b/asio/include/asio/detail/impl/epoll_reactor.ipp
index 0b83acf..5051c46 100644
--- a/asio/include/asio/detail/impl/epoll_reactor.ipp
+++ b/asio/include/asio/detail/impl/epoll_reactor.ipp
@@ -34,9 +34,9 @@
 namespace asio {
 namespace detail {
 
-epoll_reactor::epoll_reactor(asio::io_service& io_service)
-  : asio::detail::service_base<epoll_reactor>(io_service),
-    io_service_(use_service<io_service_impl>(io_service)),
+epoll_reactor::epoll_reactor(asio::execution_context& ctx)
+  : execution_context_service_base<epoll_reactor>(ctx),
+    scheduler_(use_service<scheduler>(ctx)),
     mutex_(),
     interrupter_(),
     epoll_fd_(do_epoll_create()),
@@ -85,12 +85,13 @@
 
   timer_queues_.get_all_timers(ops);
 
-  io_service_.abandon_operations(ops);
+  scheduler_.abandon_operations(ops);
 }
 
-void epoll_reactor::fork_service(asio::io_service::fork_event fork_ev)
+void epoll_reactor::fork_service(
+    asio::execution_context::fork_event fork_ev)
 {
-  if (fork_ev == asio::io_service::fork_child)
+  if (fork_ev == asio::execution_context::fork_child)
   {
     if (epoll_fd_ != -1)
       ::close(epoll_fd_);
@@ -141,7 +142,7 @@
 
 void epoll_reactor::init_task()
 {
-  io_service_.init_task();
+  scheduler_.init_task();
 }
 
 int epoll_reactor::register_descriptor(socket_type descriptor,
@@ -230,7 +231,7 @@
       if (op->perform())
       {
         descriptor_lock.unlock();
-        io_service_.post_immediate_completion(op, is_continuation);
+        scheduler_.post_immediate_completion(op, is_continuation);
         return;
       }
 
@@ -249,7 +250,7 @@
           {
             op->ec_ = asio::error_code(errno,
                 asio::error::get_system_category());
-            io_service_.post_immediate_completion(op, is_continuation);
+            scheduler_.post_immediate_completion(op, is_continuation);
             return;
           }
         }
@@ -270,7 +271,7 @@
   }
 
   descriptor_data->op_queue_[op_type].push(op);
-  io_service_.work_started();
+  scheduler_.work_started();
 }
 
 void epoll_reactor::cancel_ops(socket_type,
@@ -294,7 +295,7 @@
 
   descriptor_lock.unlock();
 
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
 }
 
 void epoll_reactor::deregister_descriptor(socket_type descriptor,
@@ -337,7 +338,7 @@
     free_descriptor_state(descriptor_data);
     descriptor_data = 0;
 
-    io_service_.post_deferred_completions(ops);
+    scheduler_.post_deferred_completions(ops);
   }
 }
 
@@ -423,7 +424,7 @@
     else
     {
       // The descriptor operation doesn't count as work in and of itself, so we
-      // don't call work_started() here. This still allows the io_service to
+      // don't call work_started() here. This still allows the scheduler to
       // stop if the only remaining operations are descriptor operations.
       descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
       descriptor_data->set_ready_events(events[i].events);
@@ -578,7 +579,7 @@
     {
       // Post the remaining completed operations for invocation.
       if (!ops_.empty())
-        reactor_->io_service_.post_deferred_completions(ops_);
+        reactor_->scheduler_.post_deferred_completions(ops_);
 
       // A user-initiated operation has completed, but there's no need to
       // explicitly call work_finished() here. Instead, we'll take advantage of
@@ -589,7 +590,7 @@
       // No user-initiated operations have completed, so we need to compensate
       // for the work_finished() call that the scheduler will make once this
       // operation returns.
-      reactor_->io_service_.work_started();
+      reactor_->scheduler_.work_started();
     }
   }
 
diff --git a/asio/include/asio/detail/impl/kqueue_reactor.hpp b/asio/include/asio/detail/impl/kqueue_reactor.hpp
index 1146017..0f70b0b 100644
--- a/asio/include/asio/detail/impl/kqueue_reactor.hpp
+++ b/asio/include/asio/detail/impl/kqueue_reactor.hpp
@@ -47,12 +47,12 @@
 
   if (shutdown_)
   {
-    io_service_.post_immediate_completion(op, false);
+    scheduler_.post_immediate_completion(op, false);
     return;
   }
 
   bool earliest = queue.enqueue_timer(time, timer, op);
-  io_service_.work_started();
+  scheduler_.work_started();
   if (earliest)
     interrupt();
 }
@@ -66,7 +66,7 @@
   op_queue<operation> ops;
   std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
   lock.unlock();
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
   return n;
 }
 
diff --git a/asio/include/asio/detail/impl/kqueue_reactor.ipp b/asio/include/asio/detail/impl/kqueue_reactor.ipp
index 5e65a0c..6945d0b 100644
--- a/asio/include/asio/detail/impl/kqueue_reactor.ipp
+++ b/asio/include/asio/detail/impl/kqueue_reactor.ipp
@@ -21,6 +21,7 @@
 #if defined(ASIO_HAS_KQUEUE)
 
 #include "asio/detail/kqueue_reactor.hpp"
+#include "asio/detail/scheduler.hpp"
 #include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 
@@ -38,9 +39,9 @@
 namespace asio {
 namespace detail {
 
-kqueue_reactor::kqueue_reactor(asio::io_service& io_service)
-  : asio::detail::service_base<kqueue_reactor>(io_service),
-    io_service_(use_service<io_service_impl>(io_service)),
+kqueue_reactor::kqueue_reactor(asio::execution_context& ctx)
+  : execution_context_service_base<kqueue_reactor>(ctx),
+    scheduler_(use_service<scheduler>(ctx)),
     mutex_(),
     kqueue_fd_(do_kqueue_create()),
     interrupter_(),
@@ -80,12 +81,13 @@
 
   timer_queues_.get_all_timers(ops);
 
-  io_service_.abandon_operations(ops);
+  scheduler_.abandon_operations(ops);
 }
 
-void kqueue_reactor::fork_service(asio::io_service::fork_event fork_ev)
+void kqueue_reactor::fork_service(
+    asio::execution_context::fork_event fork_ev)
 {
-  if (fork_ev == asio::io_service::fork_child)
+  if (fork_ev == asio::execution_context::fork_child)
   {
     // The kqueue descriptor is automatically closed in the child.
     kqueue_fd_ = -1;
@@ -125,7 +127,7 @@
 
 void kqueue_reactor::init_task()
 {
-  io_service_.init_task();
+  scheduler_.init_task();
 }
 
 int kqueue_reactor::register_descriptor(socket_type descriptor,
@@ -209,7 +211,7 @@
       if (op->perform())
       {
         descriptor_lock.unlock();
-        io_service_.post_immediate_completion(op, is_continuation);
+        scheduler_.post_immediate_completion(op, is_continuation);
         return;
       }
     }
@@ -225,7 +227,7 @@
   }
 
   descriptor_data->op_queue_[op_type].push(op);
-  io_service_.work_started();
+  scheduler_.work_started();
 }
 
 void kqueue_reactor::cancel_ops(socket_type,
@@ -249,7 +251,7 @@
 
   descriptor_lock.unlock();
 
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
 }
 
 void kqueue_reactor::deregister_descriptor(socket_type descriptor,
@@ -296,7 +298,7 @@
     free_descriptor_state(descriptor_data);
     descriptor_data = 0;
 
-    io_service_.post_deferred_completions(ops);
+    scheduler_.post_deferred_completions(ops);
   }
 }
 
diff --git a/asio/include/asio/detail/impl/scheduler.ipp b/asio/include/asio/detail/impl/scheduler.ipp
index fda2aed..9737928 100644
--- a/asio/include/asio/detail/impl/scheduler.ipp
+++ b/asio/include/asio/detail/impl/scheduler.ipp
@@ -17,8 +17,6 @@
 
 #include "asio/detail/config.hpp"
 
-#if !defined(ASIO_HAS_IOCP)
-
 #include "asio/detail/event.hpp"
 #include "asio/detail/limits.hpp"
 #include "asio/detail/reactor.hpp"
@@ -86,8 +84,8 @@
 };
 
 scheduler::scheduler(
-    asio::execution_context& context, std::size_t concurrency_hint)
-  : asio::detail::execution_context_service_base<scheduler>(context),
+    asio::execution_context& ctx, std::size_t concurrency_hint)
+  : asio::detail::execution_context_service_base<scheduler>(ctx),
     one_thread_(concurrency_hint == 1),
     mutex_(),
     task_(0),
@@ -123,8 +121,7 @@
   mutex::scoped_lock lock(mutex_);
   if (!shutdown_ && !task_)
   {
-    task_ = &use_service<reactor>(
-        static_cast<asio::io_service&>(this->context()));
+    task_ = &use_service<reactor>(this->context());
     op_queue_.push(&task_operation_);
     wake_one_thread_and_unlock(lock);
   }
@@ -470,6 +467,4 @@
 
 #include "asio/detail/pop_options.hpp"
 
-#endif // !defined(ASIO_HAS_IOCP)
-
 #endif // ASIO_DETAIL_IMPL_SCHEDULER_IPP
diff --git a/asio/include/asio/detail/impl/select_reactor.hpp b/asio/include/asio/detail/impl/select_reactor.hpp
index 5572472..3ca2608 100644
--- a/asio/include/asio/detail/impl/select_reactor.hpp
+++ b/asio/include/asio/detail/impl/select_reactor.hpp
@@ -50,12 +50,12 @@
 
   if (shutdown_)
   {
-    io_service_.post_immediate_completion(op, false);
+    scheduler_.post_immediate_completion(op, false);
     return;
   }
 
   bool earliest = queue.enqueue_timer(time, timer, op);
-  io_service_.work_started();
+  scheduler_.work_started();
   if (earliest)
     interrupter_.interrupt();
 }
@@ -69,7 +69,7 @@
   op_queue<operation> ops;
   std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
   lock.unlock();
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
   return n;
 }
 
diff --git a/asio/include/asio/detail/impl/select_reactor.ipp b/asio/include/asio/detail/impl/select_reactor.ipp
index d1ae2e9..b27babc 100644
--- a/asio/include/asio/detail/impl/select_reactor.ipp
+++ b/asio/include/asio/detail/impl/select_reactor.ipp
@@ -23,7 +23,6 @@
       && !defined(ASIO_HAS_KQUEUE) \
       && !defined(ASIO_WINDOWS_RUNTIME))
 
-#include "asio/detail/bind_handler.hpp"
 #include "asio/detail/fd_set_adapter.hpp"
 #include "asio/detail/select_reactor.hpp"
 #include "asio/detail/signal_blocker.hpp"
@@ -34,9 +33,28 @@
 namespace asio {
 namespace detail {
 
-select_reactor::select_reactor(asio::io_service& io_service)
-  : asio::detail::service_base<select_reactor>(io_service),
-    io_service_(use_service<io_service_impl>(io_service)),
+#if defined(ASIO_HAS_IOCP)
+class select_reactor::thread_function
+{
+public:
+  explicit thread_function(select_reactor* r)
+    : this_(r)
+  {
+  }
+
+  void operator()()
+  {
+    this_->run_thread();
+  }
+
+private:
+  select_reactor* this_;
+};
+#endif // defined(ASIO_HAS_IOCP)
+
+select_reactor::select_reactor(asio::execution_context& ctx)
+  : execution_context_service_base<select_reactor>(ctx),
+    scheduler_(use_service<scheduler_type>(ctx)),
     mutex_(),
     interrupter_(),
 #if defined(ASIO_HAS_IOCP)
@@ -47,8 +65,7 @@
 {
 #if defined(ASIO_HAS_IOCP)
   asio::detail::signal_blocker sb;
-  thread_ = new asio::detail::thread(
-      bind_handler(&select_reactor::call_run_thread, this));
+  thread_ = new asio::detail::thread(thread_function(this));
 #endif // defined(ASIO_HAS_IOCP)
 }
 
@@ -83,18 +100,19 @@
 
   timer_queues_.get_all_timers(ops);
 
-  io_service_.abandon_operations(ops);
+  scheduler_.abandon_operations(ops);
 }
 
-void select_reactor::fork_service(asio::io_service::fork_event fork_ev)
+void select_reactor::fork_service(
+    asio::execution_context::fork_event fork_ev)
 {
-  if (fork_ev == asio::io_service::fork_child)
+  if (fork_ev == asio::execution_context::fork_child)
     interrupter_.recreate();
 }
 
 void select_reactor::init_task()
 {
-  io_service_.init_task();
+  scheduler_.init_task();
 }
 
 int select_reactor::register_descriptor(socket_type,
@@ -134,7 +152,7 @@
   }
 
   bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
-  io_service_.work_started();
+  scheduler_.work_started();
   if (first)
     interrupter_.interrupt();
 }
@@ -253,15 +271,10 @@
     lock.unlock();
     op_queue<operation> ops;
     run(true, ops);
-    io_service_.post_deferred_completions(ops);
+    scheduler_.post_deferred_completions(ops);
     lock.lock();
   }
 }
-
-void select_reactor::call_run_thread(select_reactor* reactor)
-{
-  reactor->run_thread();
-}
 #endif // defined(ASIO_HAS_IOCP)
 
 void select_reactor::do_add_timer_queue(timer_queue_base& queue)
@@ -294,7 +307,7 @@
   for (int i = 0; i < max_ops; ++i)
     need_interrupt = op_queue_[i].cancel_operations(
         descriptor, ops, ec) || need_interrupt;
-  io_service_.post_deferred_completions(ops);
+  scheduler_.post_deferred_completions(ops);
   if (need_interrupt)
     interrupter_.interrupt();
 }
diff --git a/asio/include/asio/detail/impl/strand_executor_service.ipp b/asio/include/asio/detail/impl/strand_executor_service.ipp
index 909f524..6241b4a 100644
--- a/asio/include/asio/detail/impl/strand_executor_service.ipp
+++ b/asio/include/asio/detail/impl/strand_executor_service.ipp
@@ -113,7 +113,7 @@
 bool strand_executor_service::running_in_this_thread(
     const implementation_type& impl)
 {
-  return call_stack<strand_impl>::contains(impl.get());
+  return !!call_stack<strand_impl>::contains(impl.get());
 }
 
 } // namespace detail
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 9f97afc..12ed182 100644
--- a/asio/include/asio/detail/impl/win_iocp_io_service.ipp
+++ b/asio/include/asio/detail/impl/win_iocp_io_service.ipp
@@ -20,7 +20,6 @@
 #if defined(ASIO_HAS_IOCP)
 
 #include "asio/error.hpp"
-#include "asio/io_service.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/limits.hpp"
@@ -62,8 +61,8 @@
 };
 
 win_iocp_io_service::win_iocp_io_service(
-    asio::io_service& io_service, size_t concurrency_hint)
-  : asio::detail::service_base<win_iocp_io_service>(io_service),
+    asio::execution_context& ctx, size_t concurrency_hint)
+  : execution_context_service_base<win_iocp_io_service>(ctx),
     iocp_(),
     outstanding_work_(0),
     stopped_(0),
diff --git a/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp b/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp
index 85d7545..92f2bc9 100644
--- a/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp
+++ b/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp
@@ -171,7 +171,7 @@
     // Check if the reactor was created, in which case we need to close the
     // socket on the reactor as well to cancel any operations that might be
     // running there.
-    reactor* r = static_cast<reactor*>(
+    select_reactor* r = static_cast<select_reactor*>(
           interlocked_compare_exchange_pointer(
             reinterpret_cast<void**>(&reactor_), 0, 0));
     if (r)
@@ -271,7 +271,7 @@
   // Cancel any operations started via the reactor.
   if (!ec)
   {
-    reactor* r = static_cast<reactor*>(
+    select_reactor* r = static_cast<select_reactor*>(
           interlocked_compare_exchange_pointer(
             reinterpret_cast<void**>(&reactor_), 0, 0));
     if (r)
@@ -437,7 +437,7 @@
   {
     start_reactor_op(impl,
         (flags & socket_base::message_out_of_band)
-          ? reactor::except_op : reactor::read_op,
+          ? select_reactor::except_op : select_reactor::read_op,
         op);
   }
 }
@@ -529,7 +529,7 @@
     win_iocp_socket_service_base::base_implementation_type& impl,
     int op_type, reactor_op* op)
 {
-  reactor& r = get_reactor();
+  select_reactor& r = get_reactor();
   update_cancellation_thread_id(impl);
 
   if (is_open(impl))
@@ -590,7 +590,7 @@
   }
 
   // Otherwise, fall back to a reactor-based implementation.
-  reactor& r = get_reactor();
+  select_reactor& r = get_reactor();
   update_cancellation_thread_id(impl);
 
   if ((impl.state_ & socket_ops::non_blocking) != 0
@@ -603,7 +603,7 @@
           || op->ec_ == asio::error::would_block)
       {
         op->ec_ = asio::error_code();
-        r.start_op(reactor::connect_op, impl.socket_,
+        r.start_op(select_reactor::connect_op, impl.socket_,
             impl.reactor_data_, op, false, false);
         return;
       }
@@ -623,7 +623,7 @@
     // Check if the reactor was created, in which case we need to close the
     // socket on the reactor as well to cancel any operations that might be
     // running there.
-    reactor* r = static_cast<reactor*>(
+    select_reactor* r = static_cast<select_reactor*>(
           interlocked_compare_exchange_pointer(
             reinterpret_cast<void**>(&reactor_), 0, 0));
     if (r)
@@ -653,14 +653,14 @@
 #endif // defined(ASIO_ENABLE_CANCELIO)
 }
 
-reactor& win_iocp_socket_service_base::get_reactor()
+select_reactor& win_iocp_socket_service_base::get_reactor()
 {
-  reactor* r = static_cast<reactor*>(
+  select_reactor* r = static_cast<select_reactor*>(
         interlocked_compare_exchange_pointer(
           reinterpret_cast<void**>(&reactor_), 0, 0));
   if (!r)
   {
-    r = &(use_service<reactor>(io_service_));
+    r = &(use_service<select_reactor>(io_service_));
     interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
   }
   return *r;
diff --git a/asio/include/asio/detail/kqueue_reactor.hpp b/asio/include/asio/detail/kqueue_reactor.hpp
index ddd6c8a..194354d 100644
--- a/asio/include/asio/detail/kqueue_reactor.hpp
+++ b/asio/include/asio/detail/kqueue_reactor.hpp
@@ -35,7 +35,7 @@
 #include "asio/detail/timer_queue_set.hpp"
 #include "asio/detail/wait_op.hpp"
 #include "asio/error.hpp"
-#include "asio/io_service.hpp"
+#include "asio/execution_context.hpp"
 
 // Older versions of Mac OS X may not define EV_OOBAND.
 #if !defined(EV_OOBAND)
@@ -47,8 +47,10 @@
 namespace asio {
 namespace detail {
 
+class scheduler;
+
 class kqueue_reactor
-  : public asio::detail::service_base<kqueue_reactor>
+  : public execution_context_service_base<kqueue_reactor>
 {
 public:
   enum op_types { read_op = 0, write_op = 1,
@@ -73,7 +75,7 @@
   typedef descriptor_state* per_descriptor_data;
 
   // Constructor.
-  ASIO_DECL kqueue_reactor(asio::io_service& io_service);
+  ASIO_DECL kqueue_reactor(asio::execution_context& ctx);
 
   // Destructor.
   ASIO_DECL ~kqueue_reactor();
@@ -83,7 +85,7 @@
 
   // Recreate internal descriptors following a fork.
   ASIO_DECL void fork_service(
-      asio::io_service::fork_event fork_ev);
+      asio::execution_context::fork_event fork_ev);
 
   // Initialise the task.
   ASIO_DECL void init_task();
@@ -107,7 +109,7 @@
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
-    io_service_.post_immediate_completion(op, is_continuation);
+    scheduler_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
@@ -179,8 +181,8 @@
   // Get the timeout value for the kevent call.
   ASIO_DECL timespec* get_timeout(timespec& ts);
 
-  // The io_service implementation used to post completions.
-  io_service_impl& io_service_;
+  // The scheduler used to post completions.
+  scheduler& scheduler_;
 
   // Mutex to protect access to internal data.
   mutex mutex_;
diff --git a/asio/include/asio/detail/null_reactor.hpp b/asio/include/asio/detail/null_reactor.hpp
index fa6b623..bb868ad 100644
--- a/asio/include/asio/detail/null_reactor.hpp
+++ b/asio/include/asio/detail/null_reactor.hpp
@@ -17,9 +17,10 @@
 
 #include "asio/detail/config.hpp"
 
-#if defined(ASIO_WINDOWS_RUNTIME)
+#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)
 
-#include "asio/io_service.hpp"
+#include "asio/detail/scheduler_operation.hpp"
+#include "asio/execution_context.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -27,12 +28,12 @@
 namespace detail {
 
 class null_reactor
-  : public asio::detail::service_base<null_reactor>
+  : public execution_context_service_base<null_reactor>
 {
 public:
   // Constructor.
-  null_reactor(asio::io_service& io_service)
-    : asio::detail::service_base<null_reactor>(io_service)
+  null_reactor(asio::execution_context& ctx)
+    : execution_context_service_base<null_reactor>(ctx)
   {
   }
 
@@ -47,7 +48,7 @@
   }
 
   // No-op because should never be called.
-  void run(bool /*block*/, op_queue<operation>& /*ops*/)
+  void run(bool /*block*/, op_queue<scheduler_operation>& /*ops*/)
   {
   }
 
@@ -62,6 +63,6 @@
 
 #include "asio/detail/pop_options.hpp"
 
-#endif // defined(ASIO_WINDOWS_RUNTIME)
+#endif // defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)
 
 #endif // ASIO_DETAIL_NULL_REACTOR_HPP
diff --git a/asio/include/asio/detail/reactor.hpp b/asio/include/asio/detail/reactor.hpp
index 7ee1368..114e25a 100644
--- a/asio/include/asio/detail/reactor.hpp
+++ b/asio/include/asio/detail/reactor.hpp
@@ -23,7 +23,7 @@
 # include "asio/detail/kqueue_reactor.hpp"
 #elif defined(ASIO_HAS_DEV_POLL)
 # include "asio/detail/dev_poll_reactor.hpp"
-#elif defined(ASIO_WINDOWS_RUNTIME)
+#elif defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)
 # include "asio/detail/null_reactor.hpp"
 #else
 # include "asio/detail/select_reactor.hpp"
diff --git a/asio/include/asio/detail/reactor_fwd.hpp b/asio/include/asio/detail/reactor_fwd.hpp
index cddedc7..a564e99 100644
--- a/asio/include/asio/detail/reactor_fwd.hpp
+++ b/asio/include/asio/detail/reactor_fwd.hpp
@@ -20,7 +20,7 @@
 namespace asio {
 namespace detail {
 
-#if defined(ASIO_WINDOWS_RUNTIME)
+#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)
 typedef class null_reactor reactor;
 #elif defined(ASIO_HAS_IOCP)
 typedef class select_reactor reactor;
diff --git a/asio/include/asio/detail/scheduler.hpp b/asio/include/asio/detail/scheduler.hpp
index 1c1add8..3acb369 100644
--- a/asio/include/asio/detail/scheduler.hpp
+++ b/asio/include/asio/detail/scheduler.hpp
@@ -17,8 +17,6 @@
 
 #include "asio/detail/config.hpp"
 
-#if !defined(ASIO_HAS_IOCP)
-
 #include "asio/error_code.hpp"
 #include "asio/execution_context.hpp"
 #include "asio/detail/atomic_count.hpp"
@@ -37,15 +35,15 @@
 struct scheduler_thread_info;
 
 class scheduler
-  : public asio::detail::execution_context_service_base<scheduler>,
+  : public execution_context_service_base<scheduler>,
     public thread_context
 {
 public:
   typedef scheduler_operation operation;
 
   // Constructor. Specifies the number of concurrent threads that are likely to
-  // run the io_service. If set to 1 certain optimisation are performed.
-  ASIO_DECL scheduler(asio::execution_context& context,
+  // run the scheduler. If set to 1 certain optimisation are performed.
+  ASIO_DECL scheduler(asio::execution_context& ctx,
       std::size_t concurrency_hint = 0);
 
   // Destroy all user-defined handler objects owned by the service.
@@ -69,7 +67,7 @@
   // Interrupt the event processing loop.
   ASIO_DECL void stop();
 
-  // Determine whether the io_service is stopped.
+  // Determine whether the scheduler is stopped.
   ASIO_DECL bool stopped() const;
 
   // Restart in preparation for a subsequent run invocation.
@@ -185,6 +183,4 @@
 # include "asio/detail/impl/scheduler.ipp"
 #endif // defined(ASIO_HEADER_ONLY)
 
-#endif // !defined(ASIO_HAS_IOCP)
-
 #endif // ASIO_DETAIL_SCHEDULER_HPP
diff --git a/asio/include/asio/detail/select_reactor.hpp b/asio/include/asio/detail/select_reactor.hpp
index 9f0e4a4..2d67d81 100644
--- a/asio/include/asio/detail/select_reactor.hpp
+++ b/asio/include/asio/detail/select_reactor.hpp
@@ -35,7 +35,7 @@
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_set.hpp"
 #include "asio/detail/wait_op.hpp"
-#include "asio/io_service.hpp"
+#include "asio/execution_context.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 # include "asio/detail/thread.hpp"
@@ -47,7 +47,7 @@
 namespace detail {
 
 class select_reactor
-  : public asio::detail::service_base<select_reactor>
+  : public execution_context_service_base<select_reactor>
 {
 public:
 #if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -64,7 +64,7 @@
   };
 
   // Constructor.
-  ASIO_DECL select_reactor(asio::io_service& io_service);
+  ASIO_DECL select_reactor(asio::execution_context& ctx);
 
   // Destructor.
   ASIO_DECL ~select_reactor();
@@ -74,7 +74,7 @@
 
   // Recreate internal descriptors following a fork.
   ASIO_DECL void fork_service(
-      asio::io_service::fork_event fork_ev);
+      asio::execution_context::fork_event fork_ev);
 
   // Initialise the task, but only if the reactor is not in its own thread.
   ASIO_DECL void init_task();
@@ -92,7 +92,7 @@
   // Post a reactor operation for immediate completion.
   void post_immediate_completion(reactor_op* op, bool is_continuation)
   {
-    io_service_.post_immediate_completion(op, is_continuation);
+    scheduler_.post_immediate_completion(op, is_continuation);
   }
 
   // Start a new operation. The reactor operation will be performed when the
@@ -151,9 +151,6 @@
 #if defined(ASIO_HAS_IOCP)
   // Run the select loop in the thread.
   ASIO_DECL void run_thread();
-
-  // Entry point for the select loop thread.
-  ASIO_DECL static void call_run_thread(select_reactor* reactor);
 #endif // defined(ASIO_HAS_IOCP)
 
   // Helper function to add a new timer queue.
@@ -170,8 +167,13 @@
   ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,
       const asio::error_code& ec);
 
-  // The io_service implementation used to post completions.
-  io_service_impl& io_service_;
+  // The scheduler implementation used to post completions.
+# if defined(ASIO_HAS_IOCP)
+  typedef class win_iocp_io_service scheduler_type;
+# else // defined(ASIO_HAS_IOCP)
+  typedef class scheduler scheduler_type;
+# endif // defined(ASIO_HAS_IOCP)
+  scheduler_type& scheduler_;
 
   // Mutex to protect access to internal data.
   asio::detail::mutex mutex_;
@@ -189,6 +191,10 @@
   timer_queue_set timer_queues_;
 
 #if defined(ASIO_HAS_IOCP)
+  // Helper class to run the reactor loop in a thread.
+  class thread_function;
+  friend class thread_function;
+
   // Does the reactor loop thread need to stop.
   bool stop_thread_;
 
diff --git a/asio/include/asio/detail/signal_handler.hpp b/asio/include/asio/detail/signal_handler.hpp
index 7af1392..c34f880 100644
--- a/asio/include/asio/detail/signal_handler.hpp
+++ b/asio/include/asio/detail/signal_handler.hpp
@@ -16,9 +16,11 @@
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
 #include "asio/detail/config.hpp"
+#include "asio/detail/bind_handler.hpp"
 #include "asio/detail/fenced_block.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/handler_work.hpp"
 #include "asio/detail/memory.hpp"
 #include "asio/detail/signal_op.hpp"
 
diff --git a/asio/include/asio/detail/strand_executor_service.hpp b/asio/include/asio/detail/strand_executor_service.hpp
index 4b90a35..7a0b469 100644
--- a/asio/include/asio/detail/strand_executor_service.hpp
+++ b/asio/include/asio/detail/strand_executor_service.hpp
@@ -72,7 +72,7 @@
 
   typedef shared_ptr<strand_impl> implementation_type;
 
-  // Construct a new strand service for the specified io_service.
+  // Construct a new strand service for the specified context.
   ASIO_DECL explicit strand_executor_service(execution_context& context);
 
   // Destroy all user-defined handler objects owned by the service.
diff --git a/asio/include/asio/detail/win_iocp_io_service.hpp b/asio/include/asio/detail/win_iocp_io_service.hpp
index a1c4180..ad6f92f 100644
--- a/asio/include/asio/detail/win_iocp_io_service.hpp
+++ b/asio/include/asio/detail/win_iocp_io_service.hpp
@@ -19,7 +19,6 @@
 
 #if defined(ASIO_HAS_IOCP)
 
-#include "asio/io_service.hpp"
 #include "asio/detail/limits.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/op_queue.hpp"
@@ -32,6 +31,7 @@
 #include "asio/detail/wait_op.hpp"
 #include "asio/detail/win_iocp_operation.hpp"
 #include "asio/detail/win_iocp_thread_info.hpp"
+#include "asio/execution_context.hpp"
 
 #include "asio/detail/push_options.hpp"
 
@@ -41,13 +41,13 @@
 class wait_op;
 
 class win_iocp_io_service
-  : public asio::detail::service_base<win_iocp_io_service>,
+  : public execution_context_service_base<win_iocp_io_service>,
     public thread_context
 {
 public:
   // Constructor. Specifies a concurrency hint that is passed through to the
   // underlying I/O completion port.
-  ASIO_DECL win_iocp_io_service(asio::io_service& io_service,
+  ASIO_DECL win_iocp_io_service(asio::execution_context& ctx,
       size_t concurrency_hint = 0);
 
   // Destroy all user-defined handler objects owned by the service.
diff --git a/asio/include/asio/detail/win_iocp_socket_service.hpp b/asio/include/asio/detail/win_iocp_socket_service.hpp
index 5c653bb..1c208d1 100644
--- a/asio/include/asio/detail/win_iocp_socket_service.hpp
+++ b/asio/include/asio/detail/win_iocp_socket_service.hpp
@@ -31,8 +31,8 @@
 #include "asio/detail/memory.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/operation.hpp"
-#include "asio/detail/reactor.hpp"
 #include "asio/detail/reactor_op.hpp"
+#include "asio/detail/select_reactor.hpp"
 #include "asio/detail/socket_holder.hpp"
 #include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
@@ -341,7 +341,7 @@
     ASIO_HANDLER_CREATION((p.p, "socket",
           &impl, "async_send_to(null_buffers)"));
 
-    start_reactor_op(impl, reactor::write_op, p.p);
+    start_reactor_op(impl, select_reactor::write_op, p.p);
     p.v = p.p = 0;
   }
 
diff --git a/asio/include/asio/detail/win_iocp_socket_service_base.hpp b/asio/include/asio/detail/win_iocp_socket_service_base.hpp
index 1815935..aeccd87 100644
--- a/asio/include/asio/detail/win_iocp_socket_service_base.hpp
+++ b/asio/include/asio/detail/win_iocp_socket_service_base.hpp
@@ -30,8 +30,8 @@
 #include "asio/detail/memory.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/operation.hpp"
-#include "asio/detail/reactor.hpp"
 #include "asio/detail/reactor_op.hpp"
+#include "asio/detail/select_reactor.hpp"
 #include "asio/detail/socket_holder.hpp"
 #include "asio/detail/socket_ops.hpp"
 #include "asio/detail/socket_types.hpp"
@@ -68,7 +68,7 @@
     socket_ops::shared_cancel_token_type cancel_token_;
 
     // Per-descriptor data used by the reactor.
-    reactor::per_descriptor_data reactor_data_;
+    select_reactor::per_descriptor_data reactor_data_;
 
 #if defined(ASIO_ENABLE_CANCELIO)
     // The ID of the thread from which it is safe to cancel asynchronous
@@ -248,7 +248,7 @@
     ASIO_HANDLER_CREATION((p.p, "socket",
           &impl, "async_send(null_buffers)"));
 
-    start_reactor_op(impl, reactor::write_op, p.p);
+    start_reactor_op(impl, select_reactor::write_op, p.p);
     p.v = p.p = 0;
   }
 
@@ -459,7 +459,7 @@
   // Helper function to get the reactor. If no reactor has been created yet, a
   // new one is obtained from the io_service and a pointer to it is cached in
   // this service.
-  ASIO_DECL reactor& get_reactor();
+  ASIO_DECL select_reactor& get_reactor();
 
   // The type of a ConnectEx function pointer, as old SDKs may not provide it.
   typedef BOOL (PASCAL *connect_ex_fn)(SOCKET,
@@ -492,7 +492,7 @@
 
   // The reactor used for performing connect operations. This object is created
   // only if needed.
-  reactor* reactor_;
+  select_reactor* reactor_;
 
   // Pointer to ConnectEx implementation.
   void* connect_ex_;
diff --git a/asio/include/asio/impl/io_service.hpp b/asio/include/asio/impl/io_service.hpp
index 119dd92..bd730e1 100644
--- a/asio/include/asio/impl/io_service.hpp
+++ b/asio/include/asio/impl/io_service.hpp
@@ -31,8 +31,8 @@
 inline Service& use_service(io_service& ios)
 {
   // Check that Service meets the necessary type requirements.
-  (void)static_cast<io_service::service*>(static_cast<Service*>(0));
-  (void)static_cast<const io_service::id*>(&Service::id);
+  (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
+  (void)static_cast<const execution_context::id*>(&Service::id);
 
   return ios.service_registry_->template use_service<Service>(ios);
 }