恢复 final_suspend 会导致错误,不会破坏协程
Resuming final_suspend causes error, not destroys coroutine
James McNellis 在他的演讲“C++ 协程简介”(https://youtu.be/ZTqHjjm86Bw?t=1898) 中说了以下内容:
协程在以下情况下被销毁:
- final_suspend恢复,
- coroutine_handle<>::destroy() 被调用,
以先到者为准。
在我的测试中,我看到(VS 2015、VS 2017 RC),在 final_suspend 上暂停的恢复协同程序反而会导致错误:
Unhandled exception at 0x010B9EDD in Awaits2017.exe: RangeChecks instrumentation code detected an out of range array access. occurred
知道这里会发生什么吗?
#include <experimental/resumable>
using namespace std;
using namespace std::experimental;
struct Coro
{
coroutine_handle<> m_coro;
Coro(coroutine_handle<> coro) : m_coro(coro) {}
struct promise_type
{
Coro get_return_object()
{
return Coro(coroutine_handle<promise_type>::from_promise(*this));
}
auto initial_suspend() { return false; }
auto final_suspend() { return true; }
void return_void() {}
};
};
Coro simple()
{
co_return;
}
int main()
{
Coro c = simple();
c.m_coro.resume(); // runtime error here
}
经验法则:
如果final_suspend
returns true
,你应该调用coroutine_handle<>::destroy()
,而不是resume()
.
如果final_suspend
returns false
,你也不应该调用destroy()
,协程会自己清理。
注意VS 2015中包含的协程不是James McNellis在视频中展示的(提案有很多修改),说明:
final_suspend is resumed
可能会造成混淆。这并不意味着 resume()
被调用。
James McNellis 在他的演讲“C++ 协程简介”(https://youtu.be/ZTqHjjm86Bw?t=1898) 中说了以下内容:
协程在以下情况下被销毁:
- final_suspend恢复,
- coroutine_handle<>::destroy() 被调用,
以先到者为准。
在我的测试中,我看到(VS 2015、VS 2017 RC),在 final_suspend 上暂停的恢复协同程序反而会导致错误:
Unhandled exception at 0x010B9EDD in Awaits2017.exe: RangeChecks instrumentation code detected an out of range array access. occurred
知道这里会发生什么吗?
#include <experimental/resumable>
using namespace std;
using namespace std::experimental;
struct Coro
{
coroutine_handle<> m_coro;
Coro(coroutine_handle<> coro) : m_coro(coro) {}
struct promise_type
{
Coro get_return_object()
{
return Coro(coroutine_handle<promise_type>::from_promise(*this));
}
auto initial_suspend() { return false; }
auto final_suspend() { return true; }
void return_void() {}
};
};
Coro simple()
{
co_return;
}
int main()
{
Coro c = simple();
c.m_coro.resume(); // runtime error here
}
经验法则:
如果
final_suspend
returnstrue
,你应该调用coroutine_handle<>::destroy()
,而不是resume()
.如果
final_suspend
returnsfalse
,你也不应该调用destroy()
,协程会自己清理。
注意VS 2015中包含的协程不是James McNellis在视频中展示的(提案有很多修改),说明:
final_suspend is resumed
可能会造成混淆。这并不意味着 resume()
被调用。