【发布时间】:2020-05-12 04:17:00
【问题描述】:
根据标准,协程只有在被挂起时才会被销毁[dcl.fct.def.coroutine]
如果为未挂起的协程调用destroy,则程序具有未定义的行为。
在协程 A 中评估 await 表达式期间,假设此事件序列对应于 [expr.await]/5.1:
- 协程 A 被挂起,因为 await-ready 为假;
- 在将控制权交给协程 A 调用者之前,协程 B 被恢复;
- 一旦 B 也被挂起,控制流将返回到协程 A 调用者。
可以在协程B恢复后挂起之前销毁协程A吗?
示例代码:
#include <coroutine>
using namespace std;
struct task
{
struct promise_type;
using handle_type = coroutine_handle<promise_type>;
struct promise_type
{
handle_type resumer = nullptr;
auto
get_return_object(){
return task{handle_type::from_promise(*this)};
}
auto
initial_suspend(){
return suspend_always {};
}
auto
unhandled_exception(){}
auto
final_suspend(){
return suspend_always{};
}
void
return_void() {}
};
handle_type handle;
void await_resume(){
handle.resume();
}
auto
await_suspend(handle_type h){
handle.promise().resumer = h;
return handle;
}
auto
await_ready(){
return false;
}
};
int main(){
task coroutine_B = [&coroutine_B]() ->task
{
coroutine_B.handle.promise().resumer.destroy();
co_return;
}();//coroutine B supended at initial suspend
task coroutine_A = [&coroutine_B]() ->task
{
co_await coroutine_B;//set coroutine_B resumer to coroutine_A handle
//then resume coroutine_B.
}();//coroutine A supended at initial suspend.
coroutine_A.handle.resume();//execute co_await coroutine_B;
//is this UB?
}
可以看到here,代码编译并运行似乎没有任何问题。
另一方面,这个显然等效的版本 here 崩溃了。
【问题讨论】:
标签: c++ language-lawyer coroutine c++20