Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;20?_C++_Asynchronous_Coroutine_C++20_C++ Coroutine - Fatal编程技术网

C++ C++;20?

C++ C++;20?,c++,asynchronous,coroutine,c++20,c++-coroutine,C++,Asynchronous,Coroutine,C++20,C++ Coroutine,我试图阅读有关调用、挂起、恢复和终止协程函数时调用的操作序列的文档(cppreference和有关特性本身的标准文档)。文档深入概述了各种扩展点,这些扩展点允许库开发人员使用库组件自定义其协同程序的行为。从高层次上看,这一语言特性似乎是经过深思熟虑的 不幸的是,我很难理解协同程序执行的机制,以及我作为一名库开发人员如何使用各种扩展点来定制所述协同程序的执行。甚至从哪里开始 以下功能位于我不完全理解的一组新自定义点中: initial\u suspend() return\u void() 返回

我试图阅读有关调用、挂起、恢复和终止协程函数时调用的操作序列的文档(cppreference和有关特性本身的标准文档)。文档深入概述了各种扩展点,这些扩展点允许库开发人员使用库组件自定义其协同程序的行为。从高层次上看,这一语言特性似乎是经过深思熟虑的

不幸的是,我很难理解协同程序执行的机制,以及我作为一名库开发人员如何使用各种扩展点来定制所述协同程序的执行。甚至从哪里开始

以下功能位于我不完全理解的一组新自定义点中:

  • initial\u suspend()
  • return\u void()
  • 返回值()
  • wait_ready()
  • wait\u suspend()
  • wait_resume()
  • final\u suspend()
  • 未处理的\u异常()
有人能用高级伪代码描述编译器在运行用户协同程序时生成的代码吗?在抽象的层次上,我试图弄清楚像
await\u suspend
await\u resume
await\u ready
await\u transform
return\u value
等函数何时被调用,它们的作用是什么,我如何使用它们来编写协同程序库


不确定这是否脱离主题,但这里的一些介绍性资源将对整个社区非常有帮助。在CPPCRO中搜索和潜入库实现并不能帮助我克服这个最初的障碍:(

概述了C++20协同程序的建议。它介绍了许多不同的想法。以下内容来自我的博客。更多信息可以在我的其他帖子中找到

在我们检查整个Hello World协同程序之前,请先浏览 各部分逐步展开,包括:

  • 共程承诺
  • 协同程序上下文
  • 共同规划的未来
  • 协同进程句柄
  • 协同程序本身
  • 实际使用协同例程的子例程
  • 整个文件包含在本文档末尾 邮局

    共程 我们用

        Future myFuture = f();
    
    这是一个简单的协程,只返回值
    42
    因为它包含关键字
    co\u return
    。任何包含关键字的函数
    co_wait
    co_return
    co_yield
    是一个协同过程

    您会注意到的第一件事是,尽管我们返回的是一个整数, 协同程序返回类型是(用户定义的)Future类型 当我们调用协同程序时,我们现在不运行函数,而是 初始化一个对象,该对象最终将为我们获取所需的值 我们的未来

    寻找承诺的类型 当我们实例化协同程序时,编译器要做的第一件事就是找到 表示此特定类型的协同程序的承诺类型

    我们告诉编译器什么承诺类型属于什么协程函数 通过为创建模板部分专门化进行签名

    template <typename R, typename P...>
    struct coroutine_trait
    {};
    
    with a member called `promise_type` that defines our Promise Type
    
    如前所述,当协同路由被实例化和 在协同路由的整个生命周期内退出

    完成后,编译器将调用
    get\u return\u object
    此用户定义函数 然后负责创建未来对象并将其返回到 协同程序安装器

    在我们的例子中,我们希望我们的未来能够与我们的合作伙伴进行沟通 所以我们用我们的合作进程来创造我们的未来。这将允许我们 未来是我们的承诺

    一旦创建了协同程序,我们需要知道是否要开始运行 或者我们是否希望它立即暂停。这是 通过调用
    Promise::initial\u suspend()
    函数完成。此函数返回 等待者,我们将在另一个帖子中看到

    在本例中,由于我们确实希望函数立即启动,因此调用
    suspend\u never
    。如果我们暂停了该函数,则需要启动 通过调用句柄上的resume方法进行协同路由

    我们需要知道调用
    co\u return
    操作符时该怎么做 协同程序。这是通过
    返回\u值
    函数完成的。在本例中,我们 将值存储在Promise中,以便以后通过Promise检索

    在发生异常的情况下,我们需要知道该怎么做。这是由
    未处理的\u异常
    函数。因为在我们的示例中,异常不应该 一旦发生,我们就中止

    最后,我们需要知道在破坏我们的协同程序之前该做些什么 在本例中,通过
    final\u suspend函数完成,因为我们要检索
    因此我们返回
    suspend\u始终
    。然后必须销毁协同程序 通过coroutine handle
    destroy
    方法。否则,如果我们返回
    suspend\u never
    协同程序一旦完成运行,就会自我销毁

    把手 句柄允许访问协同程序及其承诺 味道,当我们不需要访问承诺和 当我们需要访问承诺时,使用承诺类型的协程句柄

    template <typename _Promise = void>
    class coroutine_handle;
    
    template <>
    class coroutine_handle<void> {
    public:
        void operator()() { resume(); }
        //resumes a suspended coroutine
        void resume();
        //destroys a suspended coroutine
        void destroy();
        //determines whether the coroutine is finished
        bool done() const;
    };
    
    template <Promise>
    class coroutine_handle : public coroutine_handle<void>
    {
        //gets the promise from the handle
        Promise& promise() const;
        //gets the handle from the promise
        static coroutine_handle from_promise(Promise& promise) no_except;
    };
    
    Future对象负责将协同程序抽象到外部 我们有一个构造函数,根据 promise的
    get\u return\u对象
    实现

    析构函数破坏协同程序,因为在我们的例子中,是未来 控制是承诺的一生

    最后,我们有一句话:

    using promise_type = Promise;
    

    C++库保存u

    struct Promise 
    {
        Promise() : val (-1), done (false) {}
        std::experimental::coroutines_v1::suspend_never initial_suspend() { return {}; }
        std::experimental::coroutines_v1::suspend_always final_suspend() {
            this->done = true;
            return {}; 
        }
        Future get_return_object();
        void unhandled_exception() { abort(); }
        void return_value(int val) {
            this->val = val;
        }
        
        int val;
        bool done;    
    };
    
    Future Promise::get_return_object()
    {
        return Future { Handle::from_promise(*this) };
    }
    
    template <typename _Promise = void>
    class coroutine_handle;
    
    template <>
    class coroutine_handle<void> {
    public:
        void operator()() { resume(); }
        //resumes a suspended coroutine
        void resume();
        //destroys a suspended coroutine
        void destroy();
        //determines whether the coroutine is finished
        bool done() const;
    };
    
    template <Promise>
    class coroutine_handle : public coroutine_handle<void>
    {
        //gets the promise from the handle
        Promise& promise() const;
        //gets the handle from the promise
        static coroutine_handle from_promise(Promise& promise) no_except;
    };
    
    class [[nodiscard]] Future
    {
    public:
        explicit Future(Handle handle)
            : m_handle (handle) 
        {}
        ~Future() {
            if (m_handle) {
                m_handle.destroy();
            }
        }
        using promise_type = Promise;
        int operator()();
    private:
        Handle m_handle;    
    };
    
    int Future::operator()()
    {
        if (m_handle && m_handle.promise().done) {
            return m_handle.promise().val;
        } else {
            return -1;
        }
    }
    
    using promise_type = Promise;
    
    
    
    #include <experimental/coroutine>
    #include <iostream>
    
    struct Promise;
    class Future;
    
    using Handle = std::experimental::coroutines_v1::coroutine_handle<Promise>;
    
    struct Promise 
    {
        Promise() : val (-1), done (false) {}
        std::experimental::coroutines_v1::suspend_never initial_suspend() { return {}; }
        std::experimental::coroutines_v1::suspend_always final_suspend() {
            this->done = true;
            return {}; 
        }
        Future get_return_object();
        void unhandled_exception() { abort(); }
        void return_value(int val) {
            this->val = val;
        }
        
        int val;
        bool done;    
    };
    
    class [[nodiscard]] Future
    {
    public:
        explicit Future(Handle handle)
            : m_handle (handle) 
        {}
        ~Future() {
            if (m_handle) {
                m_handle.destroy();
            }
        }
        using promise_type = Promise;
        int operator()();
    private:
        Handle m_handle;    
    };
    
    Future Promise::get_return_object()
    {
        return Future { Handle::from_promise(*this) };
    }
    
    
    int Future::operator()()
    {
        if (m_handle && m_handle.promise().done) {
            return m_handle.promise().val;
        } else {
            return -1;
        }
    }
    
    //The Co-routine
    Future f()
    {
        co_return 42;
    }
    
    int main()
    {
        Future myFuture = f();
        std::cout << "The value of myFuture is " << myFuture() << std::endl;
        return 0;
    }