我试图将boost::asio::spawn调用两次到同一个boost::asio::io_context::strand,每次传递一个协同线,并且我希望这两个协同值可以一个接一个地执行,但它们却是并行执行的。下面的代码说明了这一点:
boost::asio::io_context ioc;
boost::asio::io_context::strand strand{ioc};
boost::asio::spawn(strand, [&](boost::asio::yield_context yield)
{
cout << "1\n";
ioc.post(yield);
cout << "2\n";
ioc.post(yield);
cout << "3\n";
});
boost::asio::spawn(strand, [&](boost::asio::yield_context yield)
{
cout << "10\n";
ioc.post(yield);
cout << "20\n";
ioc.post(yield);
cout << "30\n";
});
ioc.run();这一产出如下:
1
10
2
20
3
30当我期待:
1
2
3
10
20
30在实际代码中,第一个协同线设置一个套接字(通过解析/连接/握手的动作),第二个是发送/接收。我的意图是“附加”第二个协同线到链,并让它开始执行,只有当第一个完成。
我怎样才能达到这个效果?
编辑:更多的上下文。第一个协同线在构造函数中,第二个在成员函数中。如果我想让用户编写
Foo foo;
foo.bar();如何确保构造函数内的协同线在bar()启动之前完成?
发布于 2018-09-09 16:41:57
strand只保证它们的函数不会同时在多个线程上执行。这允许您不需要使用锁。
它们不按顺序执行单独的函数。如果您想要顺序执行,只需在第一个函数的末尾调用第二个函数:
boost::asio::io_context ioc;
boost::asio::io_context::strand strand{ioc};
auto main = [&](boost::asio::yield_context yield)
{
cout << "10\n";
ioc.post(yield);
cout << "20\n";
ioc.post(yield);
cout << "30\n";
};
boost::asio::spawn(strand, [&](boost::asio::yield_context yield)
{
cout << "1\n";
ioc.post(yield);
cout << "2\n";
ioc.post(yield);
cout << "3\n";
main();
});如果您不能从第一个调用第二个函数--我曾经使用过几次的技术--是要执行一个函数队列,因为一切都是一条龙的,不需要担心锁定:
bool executing = false;
struct ExecuteLock
{
ExecuteLock()
{
if ( !executing )
{
executing = true;
locked = true;
}
else
{
locked = false;
}
}
~ExecuteLock()
{
if ( locked )
{
executing = false;
}
}
bool locked;
};
typedef QueueFunction std::function<void(boost::asio::yield_context yield);
std::queue< QueueFunction > executeQueue;
void run( QueueFunction f )
{
boost::asio::spawn( strand, [=](boost::asio::yield_context yield)
{
ExecuteLock lock;
if (!lock.locked)
{
executeQueue.push( f );
return;
}
f();
while ( !executeQueue.empty() )
{
executeQueue.front()();
executeQueue.pop();
}
} );
}然后,您可以在每次想要执行某项操作时,只需调用run()。
https://stackoverflow.com/questions/52246373
复制相似问题