I want to use async functions that have CompletionToken with std::variant.
For example, the code example has two classes that tcp and tls. They have the same signature function async_write.
When I call async_func with deferred, that causes compile error due to return type mismatch.
After some study, I use asio::experimental::use_promise. It works fine.
See https://stackoverflow.com/a/77808212/1922763
co_await std::visit(
[&](auto& c) {
return c.async_write(
// asio::deferred // caused visit return type mismatch
asio::experimental::use_promise
);
},
con
);
It seems that asio::experimental::make_parallel_group supports only asio::deferred, IIUC.
I guess that If asio::experimental::make_parallel_group supports asio::experimental::promise, then my problem would be solved.
(combine std::visit with asio::experimental::use_promise and asio::experimental::make_parallel_group.
I understant that I use experimental features. I just wanted to notify the usecase that combines experimental features I desire.
All code
#include <boost/asio.hpp>
#include <boost/asio/experimental/parallel_group.hpp>
#include <boost/asio/experimental/promise.hpp>
#include <boost/asio/experimental/use_promise.hpp>
#include <vector>
#include <variant>
#include <iostream>
namespace asio = boost::asio;
struct tcp {
template <typename CompletionToken>
auto async_write(CompletionToken&& token) {
return asio::async_initiate<
CompletionToken,
void()
>(
[](auto completion_handler) {
std::move(completion_handler)();
},
token
);
}
};
struct tls {
template <typename CompletionToken>
auto async_write(CompletionToken&& token) {
return asio::async_initiate<
CompletionToken,
void()
>(
[](auto completion_handler) {
std::move(completion_handler)();
},
token
);
}
};
using connection = std::variant<tcp, tls>;
asio::awaitable<void> all() {
auto exe = co_await asio::this_coro::executor;
std::vector<connection> cons {tcp{}, tls{}};
#if 0
// I can do individual waiting
for (auto& con : cons) {
co_await std::visit(
[&](auto& c) {
return c.async_write(
// asio::deferred // caused visit return type mismatch
asio::experimental::use_promise
);
},
con
);
}
#else
// I want to wait all async requests parallelly like this
using op_type = asio::experimental::promise<
void(),
asio::system_executor
>;
std::vector<op_type> ops;
for (auto& con : cons) {
ops.push_back(
std::visit(
[&](auto& c) {
return c.async_write(
// asio::deferred // caused visit return type mismatch
asio::experimental::use_promise
);
},
con
)
);
}
co_await asio::experimental::make_parallel_group(ops).async_wait(
asio::experimental::wait_for_all(),
asio::deferred
// asio::experimental::use_promise // also error
);
#endif
}
int main() {
std::cout << "start" << std::endl;
asio::io_context ioc;
asio::co_spawn(ioc.get_executor(), all(), asio::detached);
ioc.run();
std::cout << "finish" << std::endl;
}
Motivation
I want to use async functions that have CompletionToken with
std::variant
. For example, the code example has two classes thattcp
andtls
. They have the same signature functionasync_write
.When I call async_func with
deferred
, that causes compile error due to return type mismatch. After some study, I useasio::experimental::use_promise
. It works fine. See https://stackoverflow.com/a/77808212/1922763So far, so good. godbolt demo with
#if 1
(individual waiting): https://godbolt.org/z/fWreK6hrnNow, I want to combine this async function call with
asio::experimental::make_parallel_group
. However I got compile error.godbolt demo with
#if 0
(parallel waiting): https://godbolt.org/z/W3s76ra5zIt seems that
asio::experimental::make_parallel_group
supports onlyasio::deferred
, IIUC. I guess that Ifasio::experimental::make_parallel_group
supportsasio::experimental::promise
, then my problem would be solved. (combinestd::visit
withasio::experimental::use_promise
andasio::experimental::make_parallel_group
.I understant that I use experimental features. I just wanted to notify the usecase that combines experimental features I desire.
All code
Environment I tried