![](/img/trans.png)
[英]Boost asio C++ 20 Coroutines: co_spawn a coroutine with a by-reference parameter unexpected result
[英]c++20 coroutines: boost asio co_spawn blocks from another coroutine
我不知道这是否是boost::asio::co_spawn
的预期行为(我确实检查了文档 1.78.0...),但是如果我调用(例如co_spawn(ctx, ..., detached)
)来自a function,这个调用是异步的,意思是这个调用不会阻塞等待完成,而是立即返回。 但是,如果我从另一个协同程序中执行相同的调用, co_spawn
将阻塞直到生成的任何内容完成。 下面是使用g++ 11.2
和 boost asio 1.78 编译的测试。
#include <iostream>
#include <thread>
#include <chrono>
#include <coroutine>
#include <boost/asio.hpp>
#include <boost/asio/experimental/as_tuple.hpp>
using namespace boost;
using namespace boost::asio;
awaitable<void> TestCoro2(io_context& ctx) {
std::cout << "test coro1 thread id = " << std::this_thread::get_id() << std::endl;
co_return;
}
awaitable<void> TestCoro1(io_context& ctx) {
std::cout << "test coro1 thread id = " << std::this_thread::get_id() << std::endl;
std::cout << "333" << std::endl;
//co_await TestCoro2(ctx);
co_spawn(ctx, TestCoro2(ctx), detached);
std::cout << "444" << std::endl;
co_return;
}
awaitable<void> TestCoro(io_context& ctx) {
std::cout << "test coro thread id = " << std::this_thread::get_id() << std::endl;
std::cout << "111" << std::endl;
co_spawn(ctx.get_executor(), TestCoro1(ctx), detached);
std::cout << "222" << std::endl;
co_return;
}
void Test1() {
io_context ctx;
auto work = require(ctx.get_executor(), execution::outstanding_work.tracked);
std::cout << "before" << std::endl;
co_spawn(ctx.get_executor(), TestCoro(ctx), detached);
std::cout << "after" << std::endl;
ctx.run();
}
int main() {
Test1();
return 0;
}
在上面的示例中,我在生成 coro 时还没有调用ctx.run()
……我希望语义仍然相似……
我的理解是,首先它会安排并返回,并且当前正在运行的协程将继续,但我想我错了。 我确实知道我也可以将这个 co_spawn 包装到一个帖子中......但我对行为的差异有点困惑......
这是预期的行为吗?
谢谢! VK
问题是您对所有协程使用相同的上下文。 co_spawn
内部使用dispatch()
来确保协程在所需的上下文中启动。 如果目标上下文与当前上下文相同,则dispatch()
会同步调用令牌。 所以协程在这种情况下是同步执行的,至少直到第一个暂停点(一些co_await
)。
您可以在协程的开头插入此行以确保它始终被调度而不是被同步调用,即使是从相同的上下文调用时也是如此:
co_await asio::post(ctx, asio::use_awaitable);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.