Home > front end >  boost/beast io_context, is it possible to call it for a second run()
boost/beast io_context, is it possible to call it for a second run()

Time:12-19

I've got simple io_context object which is used to initialize ssl_stream object (using async_resolve, async_connect and async_handshake).

On a different scope, it's used to call async_read and async_write to pass IO in that connection.

the async calls are performed from within coroutine (boost::asio::spawn(io_context_, [&](boost::asio::yield_context yield)). each one of the stages above is executed on a different such coroutine. In order to execute the coroutine, the underlying io_context of the ssl_stream should be in run() method.

However, since those 2 methods are separated, than a single run() stage wouldn't be enough. After the connection initialization will be finished, the first run() will be terminated, so a second run() instance should be called right after the second coroutine (that does the IO ops) is called)

However, I observed that the second run goes out immediately, and doesn't perform the recently inserted spawn. Any idea how to overcome this scenario ? or the only alternative is to run the whole connection lifecycle in single coroutine, or call the run on a separated thread that never quits...

Here's the semi-pseudo code of my scenario :

boost::asio::io_context io_context_;
std::optional<boost::beast::tcp_stream> stream_;
std::optional<boost::asio::ip::tcp::resolver> resolver_;

//STAGE 1

boost::asio::spawn(io_context_, [&](boost::asio::yield_context yield) {
    results = resolver_->async_resolve(host_,port_ , yield);
    ssl_stream_->next_layer().async_connect(results, yield);
    ssl_stream_->async_handshake(ssl::stream_base::client, yield);
}
try {
 io_context_.run();
} catch (...) {
}

//STAGE 2

beast::flat_buffer buffer;
http::response<http::dynamic_body> res;

boost::asio::spawn(io_context_, [&](boost::asio::yield_context yield) {
  beast::get_lowest_layer(*ssl_stream_).expires_after(kOpTimeout);
  auto sent = http::async_write(*ssl_stream_, beast_request, yield);
  auto read = http::async_read(*ssl_stream_, buffer, res, yield);
});

try { 
  io_context_.run();
  return res;
} catch (...) {
}

CodePudding user response:

It is possible, but a-typical. As documented, in order to be able to re-run after the service ran out of work (I.e. enter image description here

  • Related