【问题标题】:Create a generator in C++ using coroutines使用协程在 C++ 中创建生成器
【发布时间】:2021-02-17 09:57:43
【问题描述】:

根据 McNellis 对协程的介绍(C Coroutines 简介),我尝试编译简单协程的示例,它实际上是一个简单的计数器。 但是,当调用恢复时,会触发断言。 具体

_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;
}

请查找代码here

【问题讨论】:

    标签: c++ c++20 c++-coroutine


    【解决方案1】:

    promise_type::get_return_object() 应返回用户定义的协程结果类型 resumable_thing,而不是 promise_type&amp; 本身。

    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)) {}
        // ...
    };
    

    resumable_thing 的移动赋值运算符无意中重置了this-&gt;_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;
        }
    

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 2015-05-23
      • 2016-02-02
      • 2012-02-19
      • 2017-09-02
      • 2015-12-11
      • 1970-01-01
      • 2011-08-22
      • 2021-04-30
      相关资源
      最近更新 更多