在下面的代码中,会话协同线的参数通过引用传递。
#include <boost/asio.hpp>
#include <iostream>
boost::asio::awaitable<void> session(const std::string& name)
{
std::cout << "Starting " << name << std::endl;
auto executor = co_await boost::asio::this_coro::executor;
}
int main()
{
boost::asio::io_context io_context;
co_spawn(io_context, session("ServerA"), boost::asio::detached);
co_spawn(io_context, session("ServerB"), boost::asio::detached);
io_context.run();
return 0;
}
由于一些我不明白的原因,上面的代码导致打印启动ServerB两次。
> g++ -std=c++20 ../test-coro.cpp -o test-coro && ./test-coro
Starting ServerB
Starting ServerB
但是,当我更改coroutine参数以传递值时,它将正确地打印启动ServerA和启动ServerB。
#include <boost/asio.hpp>
#include <iostream>
boost::asio::awaitable<void> session(std::string name)
{
std::cout << "Starting " << name << std::endl;
auto executor = co_await boost::asio::this_coro::executor;
}
int main()
{
boost::asio::io_context io_context;
co_spawn(io_context, session("ServerA"), boost::asio::detached);
co_spawn(io_context, session("ServerB"), boost::asio::detached);
io_context.run();
return 0;
}
> g++ -std=c++20 ../test-coro.cpp -o test-coro && ./test-coro
Starting ServerA
Starting ServerB
它是预期的还是这是一个编译器/库错误?如果它是预期的,那么它的理由是什么呢?
环境:
Arch Linux 5.18.16-arch1-1
gcc (GCC) 12.2.0
boost版本1.79
发布于 2022-08-24 10:47:23
您可以将coroutine状态想象为包含函数调用堆栈上的内容(这是函数恢复的原因):优先选择
当协同线开始执行时,它执行以下操作:
coroutine逻辑上存储对临时字符串的引用。糟了。
我还没有检查过,但我假设Asio的可评估实现是从初始的suspend_always
开始的(对于执行器模型,这对我来说很有直觉意义)。
是的,这意味着带有任何引用参数的co_spawn
意味着必须保证引用对象的生存期。
在我的系统中,输出仅仅是
Starting
Starting
一个解决办法就是你展示的东西。为了说明寿命方面:
{
std::string a="ServerA", b="ServerB";
co_spawn(io_context, session(a), boost::asio::detached);
co_spawn(io_context, session(b), boost::asio::detached);
io_context.run();
}
也是一个有效的修补程序。对于这个简单的例子,我建议使用一个std::string_view
,不管如何:
#include <boost/asio.hpp>
#include <iomanip>
#include <iostream>
boost::asio::awaitable<void> session(std::string_view name)
{
std::cout << "Starting " << std::quoted(name) << std::endl;
auto executor = co_await boost::asio::this_coro::executor;
}
int main()
{
boost::asio::io_context io_context;
std::string const a="ServerA";
co_spawn(io_context, session(a), boost::asio::detached);
co_spawn(io_context, session("ServerB"), boost::asio::detached);
io_context.run();
}
打印
Starting "ServerA"
Starting "ServerB"
https://stackoverflow.com/questions/73471450
复制相似问题