Skip to content

Commit

Permalink
修正嵌套的 asio 协程内部启动的 ucoro 协程无法再调用 asio 协程的错误
Browse files Browse the repository at this point in the history
ucoro 协程能调用 asio 协程的关键是, local_storage 绑定了一个 io_context
但是,在 asio 协程里,再次等待 ucoro 协程的时候,此时的 ucoro 协程却失去了 io_context

因此,这个嵌套在里面的 ucoro 就无法再调用 asio 的协程了。

解决的办法是把 executor 作为参数继续传下去,在 initiate_do_invoke_ucoro_awaitable
里面调用 ucoro 的 detach() 方法时,把 executor 传进去。
  • Loading branch information
microcai committed Oct 14, 2024
1 parent 0a6da5d commit 6e59b05
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 6 deletions.
11 changes: 6 additions & 5 deletions include/ucoro/asio_glue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ namespace ucoro::asio_glue

auto await_suspend(std::coroutine_handle<typename ucoro::awaitable<T>::promise_type> continue_handle) noexcept
{
boost::asio::io_context* io;
boost::asio::any_io_executor executor;
if (continue_handle.promise().local_)
{
try
{
io = std::any_cast<boost::asio::io_context*>(*continue_handle.promise().local_);
executor = std::any_cast<boost::asio::any_io_executor>(*continue_handle.promise().local_);
}
catch (const std::bad_any_cast& e)
{
Expand All @@ -62,7 +62,7 @@ namespace ucoro::asio_glue
std::terminate();
}

boost::asio::co_spawn(*io, [this](auto continue_handle) -> boost::asio::awaitable<void>
boost::asio::co_spawn(executor, [this](auto continue_handle) -> boost::asio::awaitable<void>
{
// continue_handle
if constexpr (!std::is_void_v<T>)
Expand All @@ -88,21 +88,22 @@ namespace ucoro::asio_glue
template <typename Handler>
void operator()(Handler &&handler, ucoro::awaitable<T> *ucoro_awaitable) const
{
boost::asio::any_io_executor io_context = boost::asio::get_associated_executor(handler);
if constexpr (std::is_void_v<T>)
{
[handler = std::move(handler), ucoro_awaitable = std::move(*ucoro_awaitable)]() mutable -> ucoro::awaitable<void>
{
co_await std::move(ucoro_awaitable);
handler(boost::system::error_code());
}().detach();
}().detach(io_context);
}
else
{
[handler = std::move(handler), ucoro_awaitable = std::move(*ucoro_awaitable)]() mutable -> ucoro::awaitable<void>
{
auto return_value = co_await std::move(ucoro_awaitable);
handler(boost::system::error_code(), return_value);
}().detach();
}().detach(io_context);
}

}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_asio/test_asio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ ucoro::awaitable<void> coro_compute()

int main(int argc, char **argv)
{
coro_start(coro_compute(), &main_ioc);
coro_start(coro_compute(), boost::asio::any_io_executor(main_ioc.get_executor()));

main_ioc.run();

Expand Down

0 comments on commit 6e59b05

Please sign in to comment.