123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- //
- // experimental/co_composed.hpp
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- //
- // Copyright (c) 2003-2023 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)
- //
- #ifndef ASIO_EXPERIMENTAL_CO_COMPOSED_HPP
- #define ASIO_EXPERIMENTAL_CO_COMPOSED_HPP
- #if defined(_MSC_VER) && (_MSC_VER >= 1200)
- # pragma once
- #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
- #include "asio/detail/config.hpp"
- #include "asio/async_result.hpp"
- #include "asio/detail/push_options.hpp"
- namespace asio {
- namespace experimental {
- /// Creates an initiation function object that may be used to launch a
- /// coroutine-based composed asynchronous operation.
- /**
- * The experimental::co_composed utility simplifies the implementation of
- * composed asynchronous operations by automatically adapting a coroutine to be
- * an initiation function object for use with @c async_initiate. When awaiting
- * asynchronous operations, the coroutine automatically uses a conforming
- * intermediate completion handler.
- *
- * @param implementation A function object that contains the coroutine-based
- * implementation of the composed asynchronous operation. The first argument to
- * the function object represents the state of the operation, and may be used
- * to test for cancellation. The remaining arguments are those passed to @c
- * async_initiate after the completion token.
- *
- * @param io_objects_or_executors Zero or more I/O objects or I/O executors for
- * which outstanding work must be maintained while the operation is incomplete.
- *
- * @par Per-Operation Cancellation
- * By default, terminal per-operation cancellation is enabled for composed
- * operations that use experimental::co_composed. To disable cancellation for
- * the composed operation, or to alter its supported cancellation types, call
- * the state's @c reset_cancellation_state function.
- *
- * @par Examples
- * The following example illustrates manual error handling and explicit checks
- * for cancellation. The completion handler is invoked via a @c co_yield to the
- * state's @c complete function, which never returns.
- *
- * @code template <typename CompletionToken>
- * auto async_echo(tcp::socket& socket,
- * CompletionToken&& token)
- * {
- * return asio::async_initiate<
- * CompletionToken, void(std::error_code)>(
- * asio::experimental::co_composed(
- * [](auto state, tcp::socket& socket) -> void
- * {
- * state.reset_cancellation_state(
- * asio::enable_terminal_cancellation());
- *
- * while (!state.cancelled())
- * {
- * char data[1024];
- * auto [e1, n1] =
- * co_await socket.async_read_some(
- * asio::buffer(data),
- * asio::as_tuple(asio::deferred));
- *
- * if (e1)
- * co_yield state.complete(e1);
- *
- * if (!!state.cancelled())
- * co_yield state.complete(
- * make_error_code(asio::error::operation_aborted));
- *
- * auto [e2, n2] =
- * co_await asio::async_write(socket,
- * asio::buffer(data, n1),
- * asio::as_tuple(asio::deferred));
- *
- * if (e2)
- * co_yield state.complete(e2);
- * }
- * }, socket),
- * token, std::ref(socket));
- * } @endcode
- *
- * This next example shows exception-based error handling and implicit checks
- * for cancellation. The completion handler is invoked after returning from the
- * coroutine via @c co_return. Valid @c co_return values are specified using
- * completion signatures passed to the @c co_composed function.
- *
- * @code template <typename CompletionToken>
- * auto async_echo(tcp::socket& socket,
- * CompletionToken&& token)
- * {
- * return asio::async_initiate<
- * CompletionToken, void(std::error_code)>(
- * asio::experimental::co_composed<
- * void(std::error_code)>(
- * [](auto state, tcp::socket& socket) -> void
- * {
- * try
- * {
- * state.throw_if_cancelled(true);
- * state.reset_cancellation_state(
- * asio::enable_terminal_cancellation());
- *
- * for (;;)
- * {
- * char data[1024];
- * std::size_t n = co_await socket.async_read_some(
- * asio::buffer(data), asio::deferred);
- *
- * co_await asio::async_write(socket,
- * asio::buffer(data, n), asio::deferred);
- * }
- * }
- * catch (const std::system_error& e)
- * {
- * co_return {e.code()};
- * }
- * }, socket),
- * token, std::ref(socket));
- * } @endcode
- */
- template <completion_signature... Signatures,
- typename Implementation, typename... IoObjectsOrExecutors>
- auto co_composed(Implementation&& implementation,
- IoObjectsOrExecutors&&... io_objects_or_executors);
- } // namespace experimental
- } // namespace asio
- #include "asio/detail/pop_options.hpp"
- #include "asio/experimental/impl/co_composed.hpp"
- #endif // ASIO_EXPERIMENTAL_CO_COMPOSED_HPP
|