Added new overloads of experimental::make_parallel_group that may be used
to launch a dynamically-sized set of asynchronous operations, where all
operations are the same type. For example:
using op_type = decltype(
socket1.async_read_some(
boost::asio::buffer(data1),
boost::asio::deferred
)
);
std::vector<op_type> ops;
ops.push_back(
socket1.async_read_some(
boost::asio::buffer(data1),
boost::asio::deferred
)
);
ops.push_back(
socket2.async_read_some(
boost::asio::buffer(data2),
boost::asio::deferred
)
);
boost::asio::experimental::make_parallel_group(ops).async_wait(
boost::asio::experimental::wait_for_all(),
[](
std::vector<std::size_t> completion_order,
std::vector<boost::system::error_code> e,
std::vector<std::size_t> n
)
{
for (std::size_t i = 0; i < completion_order.size(); ++i)
{
std::size_t idx = completion_order[i];
std::cout << "socket " << idx << " finished: ";
std::cout << e[idx] << ", " << n[idx] << "\n";
}
}
);
Thanks go to Klemens Morgenstern for supplying part of this implementation.
Added new spawn() overloads that conform to the requirements for
asynchronous operations. These overloads also support cancellation. When
targeting C++11 and later these functions are implemented in terms of
Boost.Context directly.
The existing overloads have been retained but are deprecated.
This is no longer an experimental facility. The names deferred and
deferred_t have been temporarily retained as deprecated entities under
the asio::experimental namespace, for backwards compatibility.
This is no longer an experimental facility. The names append and
append_t have been temporarily retained as deprecated entities under
the asio::experimental namespace, for backwards compatibility.
This is no longer an experimental facility. The names as_tuple and
as_tuple_t have been temporarily retained as deprecated entities under
the asio::experimental namespace, for backwards compatibility.
This change adds support for stream-oriented and random-access files.
For example, to write to a newly created stream-oriented file:
asio::stream_file file(
my_io_context, "/path/to/file",
asio::stream_file::write_only
| asio::stream_file::create
| asio::stream_file::truncate);
file.async_write_some(my_buffer,
[](error_code e, size_t n)
{
// ...
});
or to read from a random-access file:
asio::random_access_file file(
my_io_context, "/path/to/file",
asio::random_access_file::read_only);
file.async_read_some_at(1234, my_buffer,
[](error_code e, size_t n)
{
// ...
});
This feature currently supports I/O completion ports on Windows, and
io_uring on Linux (define BOOST_ASIO_HAS_IO_URING to enable).
The experimental::deferred completion token takes a call to an
asynchronous operation's initiating function and turns it into a
function object that accepts a completion token. For example:
auto deferred_op =
timer.async_wait(
boost::asio::experimental::deferred);
...
std::move(deferred_op)(
[](std::error_code ec){ ... });
or
auto deferred_op =
timer.async_wait(
boost::asio::experimental::deferred);
...
std::future<void> =
std::move(deferred_op)(
boost::asio::use_future);
The deferred token also supports chaining, to create simple
compositions:
auto deferred_op =
timer.async_wait(
boost::asio::experimental::deferred(
[&](std::error_code ec)
{
timer.expires_after(
std::chrono::seconds(1));
return timer.async_wait(
boost::asio::experimental::deferred);
});
...
std::future<void> = std::move(deferred_op)(boost::asio::use_future);
The as_tuple completion token adapter can be used to specify that the
completion handler arguments should be combined into a single tuple
argument.
The as_tuple adapter may be used in conjunction with use_awaitable and
structured bindings as follows:
auto [e, n] = co_await socket.async_read_some(
asio::buffer(data), as_tuple(use_awaitable));
Alternatively, it may be used as a default completion token like so:
using default_token = as_tuple_t<use_awaitable_t<>>;
using tcp_socket = default_token::as_default_on_t<tcp::socket>;
// ...
awaitable<void> do_read(tcp_socket socket)
{
// ...
auto [e, n] = co_await socket.async_read_some(asio::buffer(data));
// ...
}
The as_single completion token 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.
The as_single adapter may be used in conjunction with use_awaitable and
structured bindings as follows:
auto [e, n] = co_await socket.async_read_some(
boost::asio::buffer(data), as_single(use_awaitable));
Alternatively, it may be used as a default completion token like so:
using default_token = as_single_t<use_awaitable_t<>>;
using tcp_socket = default_token::as_default_on_t<tcp::socket>;
// ...
awaitable<void> do_read(tcp_socket socket)
{
// ...
auto [e, n] = co_await socket.async_read_some(boost::asio::buffer(data));
// ...
}