asio::awaitable<void> progress(auto strand) {
int i = 0;
for (;;) {
co_await dispatch(bind_executor(strand, asio::deferred));
ore::util::print("Strand Executor 1:", ++i);
// ...Do something with a synchronous resource...
co_await dispatch(asio::deferred);
ore::util::print("Back on IO Context Executor");
// ...Code that doesn't depend on the synchronous resource...
co_await dispatch(bind_executor(strand, asio::deferred));
ore::util::print("Strand Executor 2");
// ... Code that depends on the synchronous resource again...
}
}
int main() {
asio::io_context io;
auto my_strand = make_strand(io);
co_spawn(io, progress(my_strand), asio::detached);
io.run();
}
这是(至少)一个问题,我对此感到好奇。因为我将链定义为:
auto my_strand = make_strand(io);
...
T0 Strand Executor 1: 2657
T0 Back on IO Context Executor
Segmentation fault (core dumped)
如果链来自不同的线程,则该作品的迭代正常运行:
asio::thread_pool tp(1);
auto my_strand = make_strand(tp);
...进行更多测试,我注意到它在更简单的测试中进行了测试:
asio::awaitable<void> progress() {
for (;;) {
co_await dispatch(asio::deferred);
}
}
int main() {
asio::io_context io;
co_spawn(io, progress(), asio::detached);
io.run();
}
也许Segfault与堆叠的Coroutine实现有关吗?我认为这应该是无堆的,但也许不是这样。
这三个问题:
为什么这是segfault?为什么我在单独的executor上创建链,不是segfault
这是思考和创建链的正确方法?
注:由this Blog Post修改的代码dispatch
post
没有这样的问题。使用dispatch
允许ASIO在某些情况下“绕过”调度程序(其中至少是运行线程满足调度程序的需求,例如链接可用性),并直接在同一堆栈框架上调用处理程序。
该函数用于要求链在其基础执行程序上执行给定功能对象。如果Strand并不忙,则该功能对象将在此函数内执行,并且如果基础执行程序的dispatch()函数也能够在返回之前执行该函数。
与the the the direct Docs的compare:
post
:
此功能提交一个使用对象的对象进行执行 关联的执行人。函数对象为执行,并且 在从当前线程返回之前,请勿从当前线程调用 post().
使用post()而不是延期,表示呼叫者的使用 偏爱函数对象被热切排队以执行。这里是由于Coroutine模型,无限环路是无限的递归。至少每次迭代一次打破直接调用链,您应该没事。 Caveat
,也要注意,将执行者切换到Coroutines中可能是反模式。我知道这是一个经常发生的问题,但我觉得这可能主要来自直接将基于相互排除到Asio Strand范式的老式并发的人。我想您会更快乐地拥抱信号(例如使用timers
,或者也许是类似的信号,例如https://klemens.dev/sam/)或Channels