summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp
diff options
context:
space:
mode:
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.ipp70
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;
}