Я пытаюсь реализовать трубопровод HTTP 1.1 с использованием Boost Asio, Boost Beast и Coroutines. />
После получения запроса он порождает новую Coroutine для обработки запроса с помощью CO_SPAWN (исполнитель, обработчик (запрос), use_awaitable) < /code> и отправляет полученный ожидаемый ожидаемый в кораутину ответы через канал. Коратики (к моему удивлению) не выполняются одновременно.
Я вставил в свой обработчик 1 секунду (который ожидается, так что это не должно остановить исполнение), что сделало это легко. Эти обработчики выполняются одновременно, в то же время способным получить результаты?
Я думал об использовании каналов (и использовании отдельных < /code> вместо use_awaitable < /code>) для этого тоже, но это также кажется немного излишним, и, как у меня, где-то не понимается. PrettyPrint-Override ">auto operator()(auto stream, std::stop_token stop_token) noexcept -> boost::asio::awaitable
{
auto executor = co_await boost::asio::this_coro::executor;
boost::asio::experimental::channel channel(executor, response_queue_size_);
boost::asio::co_spawn(executor, response_worker(channel, stream), boost::asio::detached);
std::stop_callback stop_callback(stop_token, [&]() {
boost::asio::co_spawn(executor, helper::close_stream(stream), boost::asio::detached);
});
boost::asio::streambuf buffer{};
while (!stop_token.stop_requested()) {
boost::beast::http::request_parser parser{};
const auto [ec, _] = co_await boost::beast::http::async_read_header(stream, buffer, parser, boost::asio::as_tuple(boost::asio::deferred));
if (!channel.is_open()) {
//the responder closed the channel and the stream
co_return;
}
if (ec == boost::asio::error::operation_aborted) {
//the stream is closed already
break;
}
if (ec) {
co_await helper::close_stream(stream);
break;
}
co_await channel.async_send({}, boost::asio::co_spawn(executor, handler(parser, stop_token, stream, buffer), boost::asio::use_awaitable));
}
//tell the responder to stop
co_await channel.async_send(boost::asio::error::eof, {});
}
auto response_worker(boost::asio::experimental::channel &channel, auto &stream) -> boost::asio::awaitable
{
while (true) {
auto [ec, response_awaitable] = co_await channel.async_receive(boost::asio::as_tuple);
if (ec == boost::asio::error::eof || !response_awaitable.has_value())
co_return channel.close();
http_handler_result_t handler_result = co_await *std::move(response_awaitable);
std::visit(
[&](auto &response) {
response.set(
boost::beast::http::field::keep_alive,
std::format("max={}, timeout={}", response_queue_size_, std::chrono::duration_cast(header_read_timeout_).count()));
response.set(
boost::beast::http::field::connection,
"Keep-Alive");
response.prepare_payload();
},
handler_result);
bool need_eof = std::visit(
[&](const auto &response) {
return response.need_eof();
},
handler_result);
if (const auto [ec2, _] = co_await boost::beast::async_write(
stream,
std::visit(
[](auto response) {
return boost::beast::http::message_generator{std::move(response)};
},
std::move(handler_result)),
boost::asio::as_tuple)) {
//log
}
if (need_eof) {
channel.close();
co_await helper::close_stream(stream);
co_return;
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... -while-awa