diff options
Diffstat (limited to '3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp')
-rw-r--r-- | 3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp | 70 |
1 files changed, 62 insertions, 8 deletions
diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp b/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp index d4a16381d8d..37e32507288 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.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) @@ -24,6 +24,7 @@ #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/limits.hpp" +#include "asio/detail/thread.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/win_iocp_io_context.hpp" @@ -32,6 +33,22 @@ namespace asio { namespace detail { +struct win_iocp_io_context::thread_function +{ + explicit thread_function(win_iocp_io_context* s) + : this_(s) + { + } + + void operator()() + { + asio::error_code ec; + this_->run(ec); + } + + win_iocp_io_context* this_; +}; + struct win_iocp_io_context::work_finished_on_block_exit { ~work_finished_on_block_exit() @@ -62,7 +79,7 @@ struct win_iocp_io_context::timer_thread_function }; win_iocp_io_context::win_iocp_io_context( - asio::execution_context& ctx, int concurrency_hint) + asio::execution_context& ctx, int concurrency_hint, bool own_thread) : execution_context_service_base<win_iocp_io_context>(ctx), iocp_(), outstanding_work_(0), @@ -84,6 +101,22 @@ win_iocp_io_context::win_iocp_io_context( asio::error::get_system_category()); asio::detail::throw_error(ec, "iocp"); } + + if (own_thread) + { + ::InterlockedIncrement(&outstanding_work_); + thread_.reset(new asio::detail::thread(thread_function(this))); + } +} + +win_iocp_io_context::~win_iocp_io_context() +{ + if (thread_.get()) + { + stop(); + thread_->join(); + thread_.reset(); + } } void win_iocp_io_context::shutdown() @@ -97,6 +130,14 @@ void win_iocp_io_context::shutdown() ::SetWaitableTimer(waitable_timer_.handle, &timeout, 1, 0, 0, FALSE); } + if (thread_.get()) + { + stop(); + thread_->join(); + thread_.reset(); + ::InterlockedDecrement(&outstanding_work_); + } + while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0) { op_queue<win_iocp_operation> ops; @@ -159,7 +200,7 @@ size_t win_iocp_io_context::run(asio::error_code& ec) thread_call_stack::context ctx(this, this_thread); size_t n = 0; - while (do_one(INFINITE, ec)) + while (do_one(INFINITE, this_thread, ec)) if (n != (std::numeric_limits<size_t>::max)()) ++n; return n; @@ -177,7 +218,7 @@ size_t win_iocp_io_context::run_one(asio::error_code& ec) win_iocp_thread_info this_thread; thread_call_stack::context ctx(this, this_thread); - return do_one(INFINITE, ec); + return do_one(INFINITE, this_thread, ec); } size_t win_iocp_io_context::wait_one(long usec, asio::error_code& ec) @@ -192,7 +233,7 @@ size_t win_iocp_io_context::wait_one(long usec, asio::error_code& ec) win_iocp_thread_info this_thread; thread_call_stack::context ctx(this, this_thread); - return do_one(usec < 0 ? INFINITE : ((usec - 1) / 1000 + 1), ec); + return do_one(usec < 0 ? INFINITE : ((usec - 1) / 1000 + 1), this_thread, ec); } size_t win_iocp_io_context::poll(asio::error_code& ec) @@ -208,7 +249,7 @@ size_t win_iocp_io_context::poll(asio::error_code& ec) thread_call_stack::context ctx(this, this_thread); size_t n = 0; - while (do_one(0, ec)) + while (do_one(0, this_thread, ec)) if (n != (std::numeric_limits<size_t>::max)()) ++n; return n; @@ -226,7 +267,7 @@ size_t win_iocp_io_context::poll_one(asio::error_code& ec) win_iocp_thread_info this_thread; thread_call_stack::context ctx(this, this_thread); - return do_one(0, ec); + return do_one(0, this_thread, ec); } void win_iocp_io_context::stop() @@ -246,6 +287,17 @@ void win_iocp_io_context::stop() } } +bool win_iocp_io_context::can_dispatch() +{ + return thread_call_stack::contains(this) != 0; +} + +void win_iocp_io_context::capture_current_exception() +{ + if (thread_info_base* this_thread = thread_call_stack::contains(this)) + this_thread->capture_current_exception(); +} + void win_iocp_io_context::post_deferred_completion(win_iocp_operation* op) { // Flag the operation as ready. @@ -355,7 +407,8 @@ void win_iocp_io_context::on_completion(win_iocp_operation* op, } } -size_t win_iocp_io_context::do_one(DWORD msec, asio::error_code& ec) +size_t win_iocp_io_context::do_one(DWORD msec, + win_iocp_thread_info& this_thread, asio::error_code& ec) { for (;;) { @@ -417,6 +470,7 @@ size_t win_iocp_io_context::do_one(DWORD msec, asio::error_code& ec) (void)on_exit; op->complete(this, result_ec, bytes_transferred); + this_thread.rethrow_pending_exception(); ec = asio::error_code(); return 1; } |