Chris@16: // Chris@16: // detail/impl/strand_service.hpp Chris@16: // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chris@16: // Chris@101: // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: Chris@16: #ifndef BOOST_ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP Chris@16: #define BOOST_ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP Chris@16: Chris@16: #if defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: # pragma once Chris@16: #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace asio { Chris@16: namespace detail { Chris@16: Chris@16: inline strand_service::strand_impl::strand_impl() Chris@16: : operation(&strand_service::do_complete), Chris@16: locked_(false) Chris@16: { Chris@16: } Chris@16: Chris@16: struct strand_service::on_dispatch_exit Chris@16: { Chris@16: io_service_impl* io_service_; Chris@16: strand_impl* impl_; Chris@16: Chris@16: ~on_dispatch_exit() Chris@16: { Chris@16: impl_->mutex_.lock(); Chris@16: impl_->ready_queue_.push(impl_->waiting_queue_); Chris@16: bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty(); Chris@16: impl_->mutex_.unlock(); Chris@16: Chris@16: if (more_handlers) Chris@16: io_service_->post_immediate_completion(impl_, false); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: void strand_service::dispatch(strand_service::implementation_type& impl, Chris@16: Handler& handler) Chris@16: { Chris@16: // If we are already in the strand then the handler can run immediately. Chris@16: if (call_stack::contains(impl)) Chris@16: { Chris@16: fenced_block b(fenced_block::full); Chris@16: boost_asio_handler_invoke_helpers::invoke(handler, handler); Chris@16: return; Chris@16: } Chris@16: Chris@16: // Allocate and construct an operation to wrap the handler. Chris@16: typedef completion_handler op; Chris@16: typename op::ptr p = { boost::asio::detail::addressof(handler), Chris@16: boost_asio_handler_alloc_helpers::allocate( Chris@16: sizeof(op), handler), 0 }; Chris@16: p.p = new (p.v) op(handler); Chris@16: Chris@16: BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "dispatch")); Chris@16: Chris@16: bool dispatch_immediately = do_dispatch(impl, p.p); Chris@16: operation* o = p.p; Chris@16: p.v = p.p = 0; Chris@16: Chris@16: if (dispatch_immediately) Chris@16: { Chris@16: // Indicate that this strand is executing on the current thread. Chris@16: call_stack::context ctx(impl); Chris@16: Chris@16: // Ensure the next handler, if any, is scheduled on block exit. Chris@16: on_dispatch_exit on_exit = { &io_service_, impl }; Chris@16: (void)on_exit; Chris@16: Chris@16: completion_handler::do_complete( Chris@16: &io_service_, o, boost::system::error_code(), 0); Chris@16: } Chris@16: } Chris@16: Chris@16: // Request the io_service to invoke the given handler and return immediately. Chris@16: template Chris@16: void strand_service::post(strand_service::implementation_type& impl, Chris@16: Handler& handler) Chris@16: { Chris@16: bool is_continuation = Chris@16: boost_asio_handler_cont_helpers::is_continuation(handler); Chris@16: Chris@16: // Allocate and construct an operation to wrap the handler. Chris@16: typedef completion_handler op; Chris@16: typename op::ptr p = { boost::asio::detail::addressof(handler), Chris@16: boost_asio_handler_alloc_helpers::allocate( Chris@16: sizeof(op), handler), 0 }; Chris@16: p.p = new (p.v) op(handler); Chris@16: Chris@16: BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "post")); Chris@16: Chris@16: do_post(impl, p.p, is_continuation); Chris@16: p.v = p.p = 0; Chris@16: } Chris@16: Chris@16: } // namespace detail Chris@16: } // namespace asio Chris@16: } // namespace boost Chris@16: Chris@16: #include Chris@16: Chris@16: #endif // BOOST_ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP