aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Rantzsch <[email protected]>2021-03-29 13:49:55 +0200
committerHannes Rantzsch <[email protected]>2021-03-30 13:09:55 +0200
commita249cee29b3f4fed99f5a28580de1b753b80d7d5 (patch)
tree925b1501e19221e9a6b23871e5b0a3c162e7a052
parentbcda19704da482c57eb0bce786cebb97f378f146 (diff)
fix: forward executor through async_shutdown wrapper
-rw-r--r--src/lib/tls/asio/asio_stream.h50
1 files changed, 29 insertions, 21 deletions
diff --git a/src/lib/tls/asio/asio_stream.h b/src/lib/tls/asio/asio_stream.h
index 24286f10d..bef95e44a 100644
--- a/src/lib/tls/asio/asio_stream.h
+++ b/src/lib/tls/asio/asio_stream.h
@@ -334,28 +334,36 @@ class Stream
private:
/**
- * @brief Internal wrapper type to adapt the expected signature of `async_shutdown`
- * to the completion handler signature of `AsyncWriteOperation`.
+ * @brief Internal wrapper type to adapt the expected signature of `async_shutdown` to the completion handler
+ * signature of `AsyncWriteOperation`.
*
- * This is boilerplate to ignore the `size_t` parameter that is passed to the
- * completion handler of `AsyncWriteOperation`.
- *
- * @todo in C++14 and above this could be implemented as a mutable lambda expression
- * that captures `handler` by perfect forwarding, like so:
- *
- * [h = std::forward<Handler>(handler)] (...) mutable { return h(ec); }
+ * This is boilerplate to ignore the `size_t` parameter that is passed to the completion handler of
+ * `AsyncWriteOperation`. Note that it needs to retain the wrapped handler's executor.
*/
- template <typename Handler>
- class Wrapper
+ template <typename Handler, typename Executor>
+ struct Wrapper
{
- public:
- Wrapper(Handler&& handler) : _handler(std::forward<Handler>(handler)) {}
- void operator()(boost::system::error_code ec, size_t)
- {
- _handler(ec);
- }
- private:
- Handler _handler;
+ void operator()(boost::system::error_code ec, std::size_t)
+ {
+ handler(ec);
+ }
+
+ using executor_type = boost::asio::associated_executor_t<Handler, Executor>;
+
+ executor_type get_executor() const noexcept
+ {
+ return boost::asio::get_associated_executor(handler, io_executor);
+ }
+
+ using allocator_type = boost::asio::associated_allocator_t<Handler>;
+
+ allocator_type get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(handler);
+ }
+
+ Handler handler;
+ Executor io_executor;
};
public:
@@ -380,9 +388,9 @@ class Stream
// If ec is set by native_handle->close(), the AsyncWriteOperation created below will do nothing but call the
// handler with the error_code set appropriately - no need to early return here.
- using ShutdownHandlerWrapper = Wrapper<ShutdownHandler>;
+ using ShutdownHandlerWrapper = Wrapper<ShutdownHandler, typename Stream::executor_type>;
- ShutdownHandlerWrapper w(std::forward<ShutdownHandler>(handler));
+ ShutdownHandlerWrapper w{std::forward<ShutdownHandler>(handler), get_executor()};
BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, w) type_check;
boost::asio::async_completion<ShutdownHandlerWrapper, void(boost::system::error_code, std::size_t)>