Open uuuuu-diwu opened 7 months ago
co_await并没有“返回”的功能,一个协程结束后,要切换到哪个协程(相当于返回地址)是由final_suspend().await_suspend()的协程句柄决定的。 std::suspend_always()的await_suspend()这个成员函数,返回类型void,表示不返回到任何地方,直接结束当前协程,返回到调用了world.resume()的main函数里去。 PreviousAwaiter(mPrevious)的await_suspend(),返回类型是协程句柄std::coroutine_handle<>,表示返回到这个句柄指向的协程。PreviousAwaiter的await_suspend()固定返回mPrevious,而mPrevious刚好是刚才调用world时保存的调用者hello的协程句柄,所以才能返回到hello中,而不是直接退到main里。
题外话,如果你要final_suspend()返回std::suspend_always()还能继续返回到hello里的话,main就要这样写:
int main() {
world.resume();
hello.resume(); // world.resume() 遇到 std::suspend_always() 被退出了,需要main函数负责手动切换回调用者hello
}
"接结束当前协程,返回到调用了world.resume()的main函数里去。" 这个里面返回到调用了 world.resume() 的地方去我知道,但是为啥是 main 函数中,我看main里面调用的是hello.resume
说错了,是hello.resume。
对,我就是想问为啥会直接从 word 里面跳转到 hello.resume 而不是 hello 内部执行
return PreviousAwaiter(mPrevious) 等价于 mPrevious.resume() 而mPrevious是hello
为什么要用return PreviousAwaiter(mPrevious)而不是mPrevious.resume()? 因为后者会爆栈,因此C++提供了一种保证堆栈不会随着一次次返回越来越高的方法,那就是允许你返回一个你要resume的协程,让编译器在当前函数退出后,自动调用你返回的协程,称之为对称转移。 如果不考虑爆栈问题,你完全可以写mPrevious.resume(),然后只是返回void,这样更直观。 https://lewissbaker.github.io/2020/05/11/understanding_symmetric_transfer
co_await并没有“返回”的功能,一个协程结束后,要切换到哪个协程(相当于返回地址)是由final_suspend().await_suspend()的协程句柄决定的。 std::suspend_always()的await_suspend()这个成员函数,返回类型void,表示不返回到任何地方,直接结束当前协程,返回到调用了world.resume()的main函数里去。 PreviousAwaiter(mPrevious)的await_suspend(),返回类型是协程句柄std::coroutine_handle<>,表示返回到这个句柄指向的协程。PreviousAwaiter的await_suspend()固定返回mPrevious,而mPrevious刚好是刚才调用world时保存的调用者hello的协程句柄,所以才能返回到hello中,而不是直接退到main里。
题外话,如果你要final_suspend()返回std::suspend_always()还能继续返回到hello里的话,main就要这样写:
int main() { world.resume(); hello.resume(); // world.resume() 遇到 std::suspend_always() 被退出了,需要main函数负责手动切换回调用者hello }
也就是说编译器帮你resume 不算resume,只有手动resume 才算挂起点,所以返回最初的main里😘
我在 steps3.cpp 中将 40 行的 return PreviousAwaiter(mPrevious); 修改成了 return std::suspend_always(); 结果发现
world 协程 co_return 后没有返回到 hello 协成中的 co_await word() 处,按理 world 协成 co_return 完后应该会将控制权交还给之前 co_await 它的协成,求帮瞅瞅这里如何理解
auto final_suspend() noexcept { // return PreviousAwaiter(mPrevious); printf("%p exe final_suspend\n",std::coroutine_handle::from_promise(*this).address());
return std::suspend_always();
}