blah2/lib/asio-1.26.0/asio/experimental/co_composed.hpp
2023-05-04 20:55:37 +09:30

144 lines
5.1 KiB
C++

//
// experimental/co_composed.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2022 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, per-operation cancellation is disabled for composed operations
* that use experimental::co_composed. It must be explicitly enabled by calling
* 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