c++ 协程 final_suspend for promise_type
c++ coroutines final_suspend for promise_type
下面是测试空协程与 promise_type
一起玩的片段
#include <iostream>
#include <coroutine>
#define DEBUG std::cout << __PRETTY_FUNCTION__ << std::endl
struct TaskSuspendAll {
// must be of this name
struct promise_type {
TaskSuspendAll get_return_object() noexcept {
return TaskSuspendAll{
std::coroutine_handle<promise_type>::from_promise(*this)
};
}
std::suspend_always initial_suspend() noexcept {
DEBUG;
return {};
}
std::suspend_always final_suspend() noexcept {
DEBUG;
return {};
}
void unhandled_exception() {}
void return_void() {
DEBUG;
}
};
std::coroutine_handle<promise_type> ch;
};
TaskSuspendAll TestSuspendAll() {
DEBUG;
co_return;
}
int main() {
std::cout << std::endl;
auto t = TestSuspendAll();
t.ch.resume();
//t.ch.resume()
//t.ch.destroy();
return 0;
}
运行这个我得到
std::__n4861::suspend_always TaskSuspendAll::promise_type::initial_suspend()
TaskSuspendAll TestSuspendAll()
void TaskSuspendAll::promise_type::return_void()
std::__n4861::suspend_always TaskSuspendAll::promise_type::final_suspend()
我的理解是co_await
应用于initial_suspend
和final_suspend
。当我在 main
函数中调用 TestSuspendAll
时,它最终会调用 co_await promise.initial_suspend()
和 return 给调用者,因为我有 std::suspend_always
可等待。然后我恢复协程并执行 body 。在某些时候,我们将 co_await promise.final_suspend()
并再次 return 给来电者。
问题:我希望我必须进行第二次调用以恢复协程,以便 co_await promise.final_suspend()
成功并完成协程。但是,这会导致段错误。我知道在已完成的协程上调用 resume 是未定义的行为,但据我所知,它还没有 100% 完成。我的期望是 final_suspend
的行为与 initial_suspend
相同......这里的逻辑是什么?是我们必须在调用 final_suspend
后使用 destroy 吗?
非常感谢您的澄清!
VK
在其最终挂起点挂起是协程正在完成的定义。字面上地; that's what coroutine_handle::done
returns. Attempting to resume such a coroutine is UB.
所以你的期望是不正确的。
下面是测试空协程与 promise_type
一起玩的片段#include <iostream>
#include <coroutine>
#define DEBUG std::cout << __PRETTY_FUNCTION__ << std::endl
struct TaskSuspendAll {
// must be of this name
struct promise_type {
TaskSuspendAll get_return_object() noexcept {
return TaskSuspendAll{
std::coroutine_handle<promise_type>::from_promise(*this)
};
}
std::suspend_always initial_suspend() noexcept {
DEBUG;
return {};
}
std::suspend_always final_suspend() noexcept {
DEBUG;
return {};
}
void unhandled_exception() {}
void return_void() {
DEBUG;
}
};
std::coroutine_handle<promise_type> ch;
};
TaskSuspendAll TestSuspendAll() {
DEBUG;
co_return;
}
int main() {
std::cout << std::endl;
auto t = TestSuspendAll();
t.ch.resume();
//t.ch.resume()
//t.ch.destroy();
return 0;
}
运行这个我得到
std::__n4861::suspend_always TaskSuspendAll::promise_type::initial_suspend()
TaskSuspendAll TestSuspendAll()
void TaskSuspendAll::promise_type::return_void()
std::__n4861::suspend_always TaskSuspendAll::promise_type::final_suspend()
我的理解是co_await
应用于initial_suspend
和final_suspend
。当我在 main
函数中调用 TestSuspendAll
时,它最终会调用 co_await promise.initial_suspend()
和 return 给调用者,因为我有 std::suspend_always
可等待。然后我恢复协程并执行 body 。在某些时候,我们将 co_await promise.final_suspend()
并再次 return 给来电者。
问题:我希望我必须进行第二次调用以恢复协程,以便 co_await promise.final_suspend()
成功并完成协程。但是,这会导致段错误。我知道在已完成的协程上调用 resume 是未定义的行为,但据我所知,它还没有 100% 完成。我的期望是 final_suspend
的行为与 initial_suspend
相同......这里的逻辑是什么?是我们必须在调用 final_suspend
后使用 destroy 吗?
非常感谢您的澄清!
VK
在其最终挂起点挂起是协程正在完成的定义。字面上地; that's what coroutine_handle::done
returns. Attempting to resume such a coroutine is UB.
所以你的期望是不正确的。