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 | 80 |
1 files changed, 70 insertions, 10 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..1c7fb28b2d6 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-2024 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) @@ -22,8 +22,8 @@ #include "asio/error.hpp" #include "asio/detail/cstdint.hpp" #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,9 +32,25 @@ 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() + ~work_finished_on_block_exit() noexcept(false) { io_context_->work_finished(); } @@ -62,7 +78,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 +100,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 +129,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; @@ -127,7 +167,10 @@ void win_iocp_io_context::shutdown() } if (timer_thread_.get()) + { timer_thread_->join(); + timer_thread_.reset(); + } } asio::error_code win_iocp_io_context::register_handle( @@ -159,7 +202,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 +220,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 +235,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 +251,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 +269,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 +289,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 +409,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 +472,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; } @@ -473,6 +529,7 @@ size_t win_iocp_io_context::do_one(DWORD msec, asio::error_code& ec) DWORD win_iocp_io_context::get_gqcs_timeout() { +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(osvi); @@ -485,6 +542,9 @@ DWORD win_iocp_io_context::get_gqcs_timeout() return INFINITE; return default_gqcs_timeout; +#else // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) + return INFINITE; +#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) } void win_iocp_io_context::do_add_timer_queue(timer_queue_base& queue) |