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
相关推荐
Ronin30529 分钟前
【C++】类型转换
开发语言·c++
mrbone111 小时前
Git-git worktree的使用
开发语言·c++·git·cmake·worktree·gitab
浪裡遊1 小时前
Sass详解:功能特性、常用方法与最佳实践
开发语言·前端·javascript·css·vue.js·rust·sass
真实的菜1 小时前
JVM类加载系统详解:深入理解Java类的生命周期
java·开发语言·jvm
代码讲故事1 小时前
多种方法实现golang中实现对http的响应内容生成图片
开发语言·chrome·http·golang·图片·快照·截图
虾球xz2 小时前
CppCon 2018 学习:EFFECTIVE REPLACEMENT OF DYNAMIC POLYMORPHISM WITH std::variant
开发语言·c++·学习
Allen_LVyingbo2 小时前
Python常用医疗AI库以及案例解析(2025年版、上)
开发语言·人工智能·python·学习·健康医疗
小哈龙2 小时前
裸仓库 + Git Bash 搭建 本地 Git 服务端与客户端
开发语言·git·bash
G探险者2 小时前
《如何在 Spring 中实现 MQ 消息的自动重连:监听与发送双通道策略》
java·开发语言·rpc
weixin_437398213 小时前
转Go学习笔记
linux·服务器·开发语言·后端·架构·golang