diff options
Diffstat (limited to '3rdparty/asio/include/asio/detail/impl/strand_service.ipp')
-rw-r--r-- | 3rdparty/asio/include/asio/detail/impl/strand_service.ipp | 43 |
1 files changed, 34 insertions, 9 deletions
diff --git a/3rdparty/asio/include/asio/detail/impl/strand_service.ipp b/3rdparty/asio/include/asio/detail/impl/strand_service.ipp index 16946dcab67..58d657c9853 100644 --- a/3rdparty/asio/include/asio/detail/impl/strand_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/strand_service.ipp @@ -2,7 +2,7 @@ // detail/impl/strand_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -43,7 +43,8 @@ struct strand_service::on_do_complete_exit strand_service::strand_service(asio::io_context& io_context) : asio::detail::service_base<strand_service>(io_context), - io_context_(asio::use_service<io_context_impl>(io_context)), + io_context_(io_context), + io_context_impl_(asio::use_service<io_context_impl>(io_context)), mutex_(), salt_(0) { @@ -90,18 +91,44 @@ bool strand_service::running_in_this_thread( return call_stack<strand_impl>::contains(impl) != 0; } -bool strand_service::do_dispatch(implementation_type& impl, operation* op) +struct strand_service::on_dispatch_exit +{ + io_context_impl* io_context_impl_; + strand_impl* impl_; + + ~on_dispatch_exit() + { + impl_->mutex_.lock(); + impl_->ready_queue_.push(impl_->waiting_queue_); + bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty(); + impl_->mutex_.unlock(); + + if (more_handlers) + io_context_impl_->post_immediate_completion(impl_, false); + } +}; + +void strand_service::do_dispatch(implementation_type& impl, operation* op) { // If we are running inside the io_context, and no other handler already // holds the strand lock, then the handler can run immediately. - bool can_dispatch = io_context_.can_dispatch(); + bool can_dispatch = io_context_impl_.can_dispatch(); impl->mutex_.lock(); if (can_dispatch && !impl->locked_) { // Immediate invocation is allowed. impl->locked_ = true; impl->mutex_.unlock(); - return true; + + // Indicate that this strand is executing on the current thread. + call_stack<strand_impl>::context ctx(impl); + + // Ensure the next handler, if any, is scheduled on block exit. + on_dispatch_exit on_exit = { &io_context_impl_, impl }; + (void)on_exit; + + op->complete(&io_context_impl_, asio::error_code(), 0); + return; } if (impl->locked_) @@ -117,10 +144,8 @@ bool strand_service::do_dispatch(implementation_type& impl, operation* op) impl->locked_ = true; impl->mutex_.unlock(); impl->ready_queue_.push(op); - io_context_.post_immediate_completion(impl, false); + io_context_impl_.post_immediate_completion(impl, false); } - - return false; } void strand_service::do_post(implementation_type& impl, @@ -140,7 +165,7 @@ void strand_service::do_post(implementation_type& impl, impl->locked_ = true; impl->mutex_.unlock(); impl->ready_queue_.push(op); - io_context_.post_immediate_completion(impl, is_continuation); + io_context_impl_.post_immediate_completion(impl, is_continuation); } } |