summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp')
-rw-r--r--3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp148
1 files changed, 114 insertions, 34 deletions
diff --git a/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp b/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp
index a1d07bd0531..99fc94f0bdf 100644
--- a/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp
+++ b/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp
@@ -2,7 +2,7 @@
// detail/win_iocp_handle_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -20,8 +20,9 @@
#if defined(ASIO_HAS_IOCP)
+#include "asio/associated_cancellation_slot.hpp"
#include "asio/error.hpp"
-#include "asio/io_context.hpp"
+#include "asio/execution_context.hpp"
#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/detail/cstdint.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
@@ -38,7 +39,7 @@ namespace asio {
namespace detail {
class win_iocp_handle_service :
- public service_base<win_iocp_handle_service>
+ public execution_context_service_base<win_iocp_handle_service>
{
public:
// The native type of a stream handle.
@@ -75,7 +76,7 @@ public:
implementation_type* prev_;
};
- ASIO_DECL win_iocp_handle_service(asio::io_context& io_context);
+ ASIO_DECL win_iocp_handle_service(execution_context& context);
// Destroy all user-defined handler objects owned by the service.
ASIO_DECL void shutdown();
@@ -142,43 +143,61 @@ public:
// Start an asynchronous write. The data being written must be valid for the
// lifetime of the asynchronous operation.
- template <typename ConstBufferSequence, typename Handler>
+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
void async_write_some(implementation_type& impl,
- const ConstBufferSequence& buffers, Handler& handler)
+ const ConstBufferSequence& buffers,
+ Handler& handler, const IoExecutor& io_ex)
{
+ typename associated_cancellation_slot<Handler>::type slot
+ = asio::get_associated_cancellation_slot(handler);
+
// Allocate and construct an operation to wrap the handler.
- typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
+ typedef win_iocp_handle_write_op<
+ ConstBufferSequence, Handler, IoExecutor> op;
typename op::ptr p = { asio::detail::addressof(handler),
op::ptr::allocate(handler), 0 };
- p.p = new (p.v) op(buffers, handler);
+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some"));
+ // Optionally register for per-operation cancellation.
+ if (slot.is_connected())
+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
+
start_write_op(impl, 0,
buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence>::first(buffers), p.p);
+ ConstBufferSequence>::first(buffers), o);
p.v = p.p = 0;
}
// Start an asynchronous write at a specified offset. The data being written
// must be valid for the lifetime of the asynchronous operation.
- template <typename ConstBufferSequence, typename Handler>
- void async_write_some_at(implementation_type& impl, uint64_t offset,
- const ConstBufferSequence& buffers, Handler& handler)
+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>
+ void async_write_some_at(implementation_type& impl,
+ uint64_t offset, const ConstBufferSequence& buffers,
+ Handler& handler, const IoExecutor& io_ex)
{
+ typename associated_cancellation_slot<Handler>::type slot
+ = asio::get_associated_cancellation_slot(handler);
+
// Allocate and construct an operation to wrap the handler.
- typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
+ typedef win_iocp_handle_write_op<
+ ConstBufferSequence, Handler, IoExecutor> op;
typename op::ptr p = { asio::detail::addressof(handler),
op::ptr::allocate(handler), 0 };
- p.p = new (p.v) op(buffers, handler);
+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some_at"));
+ // Optionally register for per-operation cancellation.
+ if (slot.is_connected())
+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
+
start_write_op(impl, offset,
buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence>::first(buffers), p.p);
+ ConstBufferSequence>::first(buffers), o);
p.v = p.p = 0;
}
@@ -204,44 +223,64 @@ public:
// Start an asynchronous read. The buffer for the data being received must be
// valid for the lifetime of the asynchronous operation.
- template <typename MutableBufferSequence, typename Handler>
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
void async_read_some(implementation_type& impl,
- const MutableBufferSequence& buffers, Handler& handler)
+ const MutableBufferSequence& buffers,
+ Handler& handler, const IoExecutor& io_ex)
{
+ typename associated_cancellation_slot<Handler>::type slot
+ = asio::get_associated_cancellation_slot(handler);
+
// Allocate and construct an operation to wrap the handler.
- typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
+ typedef win_iocp_handle_read_op<
+ MutableBufferSequence, Handler, IoExecutor> op;
typename op::ptr p = { asio::detail::addressof(handler),
op::ptr::allocate(handler), 0 };
- p.p = new (p.v) op(buffers, handler);
+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some"));
+ // Optionally register for per-operation cancellation.
+ if (slot.is_connected())
+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
+
start_read_op(impl, 0,
buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::first(buffers), p.p);
+ MutableBufferSequence>::first(buffers), o);
p.v = p.p = 0;
}
// Start an asynchronous read at a specified offset. The buffer for the data
// being received must be valid for the lifetime of the asynchronous
// operation.
- template <typename MutableBufferSequence, typename Handler>
- void async_read_some_at(implementation_type& impl, uint64_t offset,
- const MutableBufferSequence& buffers, Handler& handler)
+ template <typename MutableBufferSequence,
+ typename Handler, typename IoExecutor>
+ void async_read_some_at(implementation_type& impl,
+ uint64_t offset, const MutableBufferSequence& buffers,
+ Handler& handler, const IoExecutor& io_ex)
{
+ typename associated_cancellation_slot<Handler>::type slot
+ = asio::get_associated_cancellation_slot(handler);
+
// Allocate and construct an operation to wrap the handler.
- typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
+ typedef win_iocp_handle_read_op<
+ MutableBufferSequence, Handler, IoExecutor> op;
typename op::ptr p = { asio::detail::addressof(handler),
op::ptr::allocate(handler), 0 };
- p.p = new (p.v) op(buffers, handler);
+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex);
ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some_at"));
+ // Optionally register for per-operation cancellation.
+ if (slot.is_connected())
+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);
+
start_read_op(impl, offset,
buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::first(buffers), p.p);
+ MutableBufferSequence>::first(buffers), o);
p.v = p.p = 0;
}
@@ -251,22 +290,24 @@ private:
const null_buffers& buffers, asio::error_code& ec);
size_t write_some_at(implementation_type& impl, uint64_t offset,
const null_buffers& buffers, asio::error_code& ec);
- template <typename Handler>
+ template <typename Handler, typename IoExecutor>
void async_write_some(implementation_type& impl,
- const null_buffers& buffers, Handler& handler);
- template <typename Handler>
+ const null_buffers& buffers, Handler& handler,
+ const IoExecutor& io_ex);
+ template <typename Handler, typename IoExecutor>
void async_write_some_at(implementation_type& impl, uint64_t offset,
- const null_buffers& buffers, Handler& handler);
+ const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);
size_t read_some(implementation_type& impl,
const null_buffers& buffers, asio::error_code& ec);
size_t read_some_at(implementation_type& impl, uint64_t offset,
const null_buffers& buffers, asio::error_code& ec);
- template <typename Handler>
+ template <typename Handler, typename IoExecutor>
void async_read_some(implementation_type& impl,
- const null_buffers& buffers, Handler& handler);
- template <typename Handler>
+ const null_buffers& buffers, Handler& handler,
+ const IoExecutor& io_ex);
+ template <typename Handler, typename IoExecutor>
void async_read_some_at(implementation_type& impl, uint64_t offset,
- const null_buffers& buffers, Handler& handler);
+ const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);
// Helper class for waiting for synchronous operations to complete.
class overlapped_wrapper;
@@ -298,6 +339,45 @@ private:
// destroyed.
ASIO_DECL void close_for_destruction(implementation_type& impl);
+ // Helper class used to implement per operation cancellation.
+ class iocp_op_cancellation : public operation
+ {
+ public:
+ iocp_op_cancellation(HANDLE h, operation* target)
+ : operation(&iocp_op_cancellation::do_complete),
+ handle_(h),
+ target_(target)
+ {
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const asio::error_code& result_ec,
+ std::size_t bytes_transferred)
+ {
+ iocp_op_cancellation* o = static_cast<iocp_op_cancellation*>(base);
+ o->target_->complete(owner, result_ec, bytes_transferred);
+ }
+
+ void operator()(cancellation_type_t type)
+ {
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ if (!!(type &
+ (cancellation_type::terminal
+ | cancellation_type::partial
+ | cancellation_type::total)))
+ {
+ ::CancelIoEx(handle_, this);
+ }
+#else // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ (void)type;
+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ }
+
+ private:
+ HANDLE handle_;
+ operation* target_;
+ };
+
// The IOCP service used for running asynchronous operations and dispatching
// handlers.
win_iocp_io_context& iocp_service_;