C++并发之协程实例(三)(co_await)

目录

  • [1 协程](#1 协程)
  • [2 实例](#2 实例)
  • [3 运行](#3 运行)

1 协程

协程(Coroutines)是一个可以挂起执行以便稍后恢复的函数。协程是无堆栈的:它们通过返回到调用方来暂停执行,并且恢复执行所需的数据与堆栈分开存储。这允许异步执行的顺序代码(例如,在没有显式回调的情况下处理非阻塞I/O),还支持惰性计算无限序列上的算法和其他用途。

协程类图如下:

2 实例

cpp 复制代码
#include <coroutine> //for std::coroutine_handle std::suspend_never
#include <iostream>
#include <utility>

template <class T>
struct task
{
    struct promise_type
    {
        auto  get_return_object()
        {
            std::cout << "in get_return_object" << std::endl;
            return task(std::coroutine_handle<promise_type>::from_promise(*this));
        }
        std::suspend_always initial_suspend() {
            std::cout << "in initial_suspend" << std::endl;
            return {}; 
        }
        struct final_awaiter
        {
            bool await_ready() noexcept
            { 
                std::cout << "in final_awaiter.await_ready" << std::endl;
                return false;
            }
            void await_resume() noexcept 
            {
                std::cout << "in final_awaiter.await_resume" << std::endl;
            }
            std::coroutine_handle<>
                await_suspend(std::coroutine_handle<promise_type> h) noexcept
            {
                std::cout << "in final_awaiter.await_suspend" << std::endl;
                if(auto previous = h.promise().previous; previous)
                {
                    std::cout << "in final_awaiter.await_suspend.previous" << std::endl;
                    return previous;
                }
                else
                {
                    std::cout << "in final_awaiter.await_suspend.noop_coroutine" << std::endl;
                    return std::noop_coroutine();
                }
            }
        };
        final_awaiter final_suspend() noexcept {
            std::cout << "in final_suspend" << std::endl;
            return {}; 
        }
        void unhandled_exception() {
            std::cout << "in unhandled_exception" << std::endl;
            throw; 
        }
        void return_value(T value) {
            std::cout << "in return_value" << std::endl;
            result = std::move(value); 
        }

        T result;
        std::coroutine_handle<> previous;
    };
    task(std::coroutine_handle<promise_type> h) : coro(h) {}
    task(task &&) = delete;
    ~task() { coro.destroy(); }

    struct awaiter
    {
        bool await_ready() 
        {
            std::cout << "in awaiter.await_ready" << std::endl;
            return false; 
        }
        T await_resume() 
        {
            std::cout << "in awaiter.await_resume" << std::endl;
            return std::move(coro.promise().result);
        }
        auto await_suspend(std::coroutine_handle<> h)
        {
            std::cout << "in awaiter.await_suspend" << std::endl;
            coro.promise().previous = h;
            return coro;
        }
        std::coroutine_handle<promise_type> coro;
    };

    awaiter operator co_await()
    { 
        std::cout << "in co_await" << std::endl;
        return awaiter{coro};
    }
    T operator()()
    {
        std::cout << "in operator()" << std::endl;
        coro.resume();
        return std::move(coro.promise().result);
    }

private:
    std::coroutine_handle<promise_type> coro;
};

task<int> get_random()
{
    std::cout << "in get_random\n";
    co_return 4;
}

task<int> test()
{
    task<int> v = get_random();
    task<int> u = get_random();
    std::cout << "in test()\n";
    int x = (co_await v + co_await u);
    co_return x;
}

int main()
{
    std::cout << "before test\n";
    task<int> t = test();
    std::cout << "after test\n";
    int result = t();
    std::cout << "after t()\n";
    std::cout << result << std::endl;
    return 0;
}

3 运行

bash 复制代码
before test
in get_return_object                             创建协程t
in initial_suspend                               挂起t
after test
in operator()                                    调用t()->{ resume, return result; }
in get_return_object                             创建携程v
in initial_suspend                               挂起v
in get_return_object                             创建携程u
in initial_suspend                               挂起u
in test()
in co_await                                      调用v.co_wait
in co_await                                      调用u.co_wait
in awaiter.await_ready                           调用v.awaiter.await_ready
in awaiter.await_suspend                         调用v.awaiter.await_suspend,保存到previous,返回原来的coro
in get_random
in return_value                                  调用v.promise_type.return_value
in final_suspend                                 调用v.promise_type.final_suspend,返回final_awaiter
in final_awaiter.await_ready                     调用v.final_awaiter.await_ready
in final_awaiter.await_suspend                   调用v.final_awaiter.await_suspend
in final_awaiter.await_suspend.previous          返回v之前的previous
in awaiter.await_ready                           调用u.awaiter.await_ready
in awaiter.await_suspend                         调用u.awaiter.await_suspend,保存到previous,返回原来的coro
in get_random
in return_value                                  调用u.promise_type.return_value
in final_suspend                                 调用u.promise_type.final_suspend,返回final_awaiter
in final_awaiter.await_ready                     调用u.final_awaiter.await_ready
in final_awaiter.await_suspend                   调用u.final_awaiter.await_suspend
in final_awaiter.await_suspend.previous          返回u之前的previous
in awaiter.await_resume                          调用v.awaiter.await_resume,返回值  
in awaiter.await_resume                          调用u.awaiter.await_resume,返回值    
in test.x
in return_value                                  调用t.promise_type.return_value
in final_suspend                                 调用t.promise_type.final_suspend,返回final_awaiter             
in final_awaiter.await_ready                     调用t.final_awaiter.await_ready
in final_awaiter.await_suspend                   调用t.final_awaiter.await_suspend
in final_awaiter.await_suspend.noop_coroutine    返回noop_coroutine,不做后续操作
after t()
8

说明:

  • 由于t挂起后立即调用resume,所以t的awaiter没有被调用,所以t.final_awaiter.await_suspend返回的是noop_coroutine
相关推荐
阿拉丁的梦1 小时前
教程1:用vscode->ptvsd-创建和调试一个UI(python)-转载官方翻译(有修正)
开发语言·python
木宇(记得热爱生活)2 小时前
一键搭建开发环境:制作bash shell脚本
开发语言·bash
Cisyam^2 小时前
Go环境搭建实战:告别Java环境配置的复杂
java·开发语言·golang
IAR Systems3 小时前
在IAR Embedded Workbench for Arm中实现Infineon TRAVEO™ T2G安全调试
开发语言·arm开发·安全·嵌入式软件开发·iar
jayzhang_3 小时前
SPARK入门
大数据·开发语言
蹦极的考拉3 小时前
网站日志里面老是出现{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22.....
android·开发语言·php
fured3 小时前
[调试][实现][原理]用Golang实现建议断点调试器
开发语言·后端·golang
大翻哥哥4 小时前
Python地理空间数据分析:从地图绘制到智能城市应用
开发语言·python·数据分析
NPE~4 小时前
[手写系列]Go手写db — — 第二版
开发语言·数据库·golang·教程·db·手写系列
M_Reus_114 小时前
Groovy集合常用简洁语法
java·开发语言·windows