AimRT/_deps/boost-src/libs/asio/doc/overview/token_adapters.qbk
2025-01-12 20:37:50 +08:00

244 lines
7.8 KiB
Plaintext

[/
/ 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)
/]
[section:token_adapters Completion Token Adapters]
A ['completion token adapter] is a utility that can be generically applied to a
[link boost_asio.overview.model.completion_tokens completion token], to produce a new
completion token with modified behaviour. Common uses of completion token
adapters include:
* Automatically wrapping the completion handler to add [link
boost_asio.overview.model.associators associated characteristics].
* Transforming the completion signature and arguments passed to the completion
handler.
Boost.Asio includes a number of completion token adapters as described below.
[heading bind_executor, bind_allocator, and bind_cancellation_slot]
The [link boost_asio.reference.bind_executor `bind_executor`] function adapts a
completion token to imbue the completion handler with an [link
boost_asio.overview.model.executors associated executor].
This example shows the `bind_executor` adapter applied to a lambda, to specify
that the handler should execute in the specified strand. The arguments to the
completion handler are passed through as-is.
my_socket.async_read_some(my_buffer,
boost::asio::bind_executor(my_strand,
[](boost::system::error_code error, std::size_t bytes_transferred)
{
// ...
}));
When applied to completion tokens that cause the initiating function to produce
a result, such as [link boost_asio.reference.use_awaitable `use_awaitable`], the
result is returned unmodified.
boost::asio::awaitable<void> my_coroutine()
{
// ...
std::size_t bytes_transferred =
co_await my_socket.async_read_some(my_buffer,
boost::asio::bind_executor(my_strand, boost::asio::use_awaitable));
// ...
}
The [link boost_asio.reference.bind_allocator `bind_allocator`] and [link
boost_asio.reference.bind_cancellation_slot `bind_cancellation_slot`] adapters work
similarly, to imbue the completion handler with an [link
boost_asio.overview.model.allocators associated allocator] or [link
boost_asio.overview.model.cancellation associated cancellation slot] respectively.
[heading redirect_error]
The [link boost_asio.reference.redirect_error `redirect_error`] function adapts a
completion token to capture the `error_code` produced by an operation into a
specified variable. In doing so, it modifies the completion signature to remove
the initial `error_code` parameter.
This example shows the `redirect_error` adapter applied to a lambda, to specify
that the error should be captured into `my_error`. The `error_code` is no
longer passed to the completion handler, but the remaining arguments are passed
through as-is.
boost::system::error_code my_error; // N.B. must be valid until operation completes
// ...
my_socket.async_read_some(my_buffer,
boost::asio::redirect_error(
[](std::size_t bytes_transferred)
{
// ...
}, my_error));
When applied to completion tokens that cause the initiating function to produce
a result, such as [link boost_asio.reference.use_awaitable `use_awaitable`], the
result is returned unmodified. However, if the operation fails, the `co_await`
expression will no longer throw an exception on resumption.
boost::asio::awaitable<void> my_coroutine()
{
// ...
boost::system::error_code my_error;
std::size_t bytes_transferred =
co_await my_socket.async_read_some(my_buffer,
boost::asio::redirect_error(boost::asio::use_awaitable, my_error));
// ...
}
[heading as_tuple]
The [link boost_asio.reference.as_tuple `as_tuple`] adapter can be used to specify
that the completion handler arguments should be combined into a single tuple
argument.
For example, the `as_tuple` adapter may be used in conjunction with [link
boost_asio.reference.use_awaitable `use_awaitable`] and structured bindings as
follows:
auto [e, n] =
co_await my_socket.async_read_some(my_buffer,
boost::asio::as_tuple(boost::asio::use_awaitable));
This adapter may also be used as a default completion token:
using default_token = boost::asio::as_tuple_t<boost::asio::use_awaitable_t<>>;
using tcp_socket = default_token::as_default_on_t<tcp::socket>;
// ...
boost::asio::awaitable<void> do_read(tcp_socket my_socket)
{
// ...
auto [e, n] = co_await my_socket.async_read_some(my_buffer);
// ...
}
[heading as_single]
[note This is an experimental feature.]
The [link boost_asio.reference.experimental__as_single `experimental::as_single`]
adapter can be used to specify that the completion handler
arguments should be combined into a single argument. For completion signatures
with a single parameter, the argument is passed through as-is. For signatures
with two or more parameters, the arguments are combined into a tuple.
For example, when applied to a timer wait operation, the single `error_code`
argument is passed directly to the completion handler:
my_timer.async_wait(
boost::asio::experimental::as_single(
[](boost::system::error_code error)
{
// ...
}));
When applied to a socket read operation, where the completion signature
specifies two parameters, the handler is passed the result as a tuple:
my_socket.async_read_some(my_buffer,
boost::asio::experimental::as_single,
[](std::tuple<boost::system::error_code, std::size_t> result)
{
// ...
}));
[heading append]
The [link boost_asio.reference.append `append`] completion token adapter can be
used to pass additional completion handler arguments at the end of the
completion signature.
For example:
timer.async_wait(
boost::asio::append(
[](boost::system::error_code ec, int i)
{
// ...
},
42
)
);
std::future<int> f = timer.async_wait(
boost::asio::append(
boost::asio::use_future,
42
)
);
[heading prepend]
The [link boost_asio.reference.prepend `prepend`] completion token adapter can be
used to pass additional completion handler arguments before the existing
completion handler arguments.
For example:
timer.async_wait(
boost::asio::prepend(
[](int i, boost::system::error_code ec)
{
// ...
},
42
)
);
std::future<std::tuple<int, boost::system::error_code>> f = timer.async_wait(
boost::asio::prepend(
boost::asio::use_future,
42
)
);
[heading consign]
The [link boost_asio.reference.consign `consign`] completion token adapter can be
used to attach additional values to a completion handler. This is typically used
to keep at least one copy of an object, such as a smart pointer, alive until the
completion handler is called.
For example:
auto timer1 = std::make_shared<boost::asio::steady_timer>(my_io_context);
timer1->expires_after(std::chrono::seconds(1));
timer1->async_wait(
boost::asio::consign(
[](boost::system::error_code ec)
{
// ...
},
timer1
)
);
auto timer2 = std::make_shared<boost::asio::steady_timer>(my_io_context);
timer2->expires_after(std::chrono::seconds(30));
std::future<void> f =
timer2->async_wait(
boost::asio::consign(
boost::asio::use_future,
timer2
)
);
[heading See Also]
[link boost_asio.reference.bind_executor bind_executor],
[link boost_asio.reference.bind_allocator bind_allocator],
[link boost_asio.reference.bind_cancellation_slot bind_cancellation_slot],
[link boost_asio.reference.redirect_error redirect_error],
[link boost_asio.reference.as_tuple as_tuple],
[link boost_asio.reference.experimental__as_single experimental::as_single],
[link boost_asio.reference.append append],
[link boost_asio.reference.prepend prepend].
[endsect]