c++ - 使用协程在 C++ 中创建生成器
问题描述
继 McNellis 对协程的介绍(Introduction to C Coroutines)之后,我尝试编译简单协程的示例,它实际上是一个简单的计数器。但是,当调用 resume 时,会触发断言。具体来说
_LIBCPP_ASSERT(!done(), "resume() 在协程完成时有未定义的行为");
我对协程没有太多经验,我无法找出问题所在。
代码如下
#include <iostream>
#include <coroutine>
using namespace std;
//using namespace experimental;
struct resumable_thing
{
struct promise_type
{
int const* _current;
promise_type & get_return_object() noexcept
{
return *this;
}
auto initial_suspend() { return suspend_always{}; }
auto final_suspend() { return suspend_always{}; }
auto yield_value(int const& value) {
_current = &value;
return suspend_always{};
}
void unhandled_exception()
{
auto ex = std::current_exception();
std::rethrow_exception(ex);
//// MSVC bug? should be possible to rethrow with "throw;"
//// rethrow exception immediately
// throw;
}
void return_void() noexcept
{
}
};
// using coroutine_handle = coroutine_handle<promise_type>;
resumable_thing() = default;
resumable_thing(resumable_thing const & ) = delete;
resumable_thing & operator = (resumable_thing const & ) =delete;
resumable_thing(promise_type && promise)
: _coroutine(coroutine_handle<promise_type>::from_promise(promise)) {}
resumable_thing(resumable_thing&& other) : _coroutine(other._coroutine)
{
other._coroutine = nullptr;
}
resumable_thing & operator = (resumable_thing const && other)
{
_coroutine = other._coroutine;
_coroutine = nullptr;
return *this;
}
explicit resumable_thing(coroutine_handle<promise_type> coroutine)
:_coroutine(coroutine)
{
}
~resumable_thing()
{
if(_coroutine)
{
_coroutine.destroy();
}
}
void resume()
{
std::cout << "coroutines resume" << std::endl;
_coroutine.resume();
}
coroutine_handle<promise_type> _coroutine = nullptr;
};
resumable_thing counter()
{
cout << "counter: called\n";
for(int i = 0 ; ++i;)
{
co_await suspend_always{};
cout << "counter: resumed (#" << i << ")\n";
}
}
int main(int argc, const char * argv[]) {
// insert code here...
cout << "main: calling counter\n";
resumable_thing the_counter = counter();
cout << "main: resuming counter\n";
the_counter.resume();//assertion is fired
cout << "main:done" << std::endl;
return 0;
}
请在此处找到代码
解决方案
promise_type::get_return_object()
应返回用户定义的协程结果类型resumable_thing
,而不是promise_type&
自身。
struct resumable_thing
{
struct promise_type
{
resumable_thing get_return_object() noexcept
{
return {*this};
}
// ...
};
resumable_thing(promise_type & promise)
: _coroutine(coroutine_handle<promise_type>::from_promise(promise)) {}
// ...
};
Andresumable_thing
的移动赋值运算符this->_coroutine
无意中重置。
// FIXED: resumable_thing const && -> resumable_thing &&
resumable_thing & operator = (resumable_thing && other)
{
_coroutine = other._coroutine;
// FIXED: _coroutine -> other._coroutine
other._coroutine = nullptr;
return *this;
}
推荐阅读
- security - 在生产环境中使用 .env 是否存在安全问题?
- javascript - 从 JavaScript 中的文本解释/提取位置值 - NodeJS
- excel - Excel 2013 中的 VBA - 启动批处理文件
- javascript - 将 HTML 解析为来自异步调用的响应
- azure - Azure 帐户自动删除
- visual-studio-code - 在 Visual Studio Code 中配置展开选择以选择整个标识符
- python - 有时,对象是不可迭代的
- java - @ManyToOne and @OneToOne on the same entity
- bash - 如何使用bash在.txt文件中用零替换列中的值
- spring - 在 restfull api 参数或正文中约会?