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); }