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 小时前
仿腾讯会议——音频服务器部分
c++·qt·面试·职场和发展·音视频·腾讯会议
DpHard2 小时前
自用Vscode 配置c++ debug环境
c++·ide·vscode
风逸hhh3 小时前
python打卡day29@浙大疏锦行
开发语言·前端·python
ᖰ・◡・ᖳ3 小时前
JavaScript:PC端特效--缓动动画
开发语言·前端·javascript·css·学习·html5
hy____1233 小时前
C++多态的详细讲解
开发语言·c++
superior tigre3 小时前
C++学习:六个月从基础到就业——C++20:范围(Ranges)进阶
c++·学习·c++20
小葡萄20253 小时前
黑马程序员C++2024版笔记 第0章 C++入门
开发语言·c++·笔记
万物此臻3 小时前
C#编写软件添加菜单栏
开发语言·c#
不二一4 小时前
linux c++头文件生成源文件 使用python脚本 配置vim快捷键
linux·c++·python
RongSen334 小时前
Python海龟绘图(Turtle Graphics)核心函数和关键要点
开发语言·python