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
相关推荐
A尘埃7 分钟前
Java业务场景(高并发+高可用+分布式)
java·开发语言·分布式
晨曦夜月9 分钟前
头文件与目标文件的关系
linux·开发语言·c++
刃神太酷啦13 分钟前
C++ list 容器全解析:从构造到模拟实现的深度探索----《Hello C++ Wrold!》(16)--(C/C++)
java·c语言·c++·qt·算法·leetcode·list
wearegogog12313 分钟前
C# 条码打印程序(一维码 + 二维码)
java·开发语言·c#
9527(●—●)14 分钟前
windows系统python开发pip命令使用(菜鸟学习)
开发语言·windows·python·学习·pip
松涛和鸣20 分钟前
32、Linux线程编程
linux·运维·服务器·c语言·开发语言·windows
sali-tec20 分钟前
C# 基于halcon的视觉工作流-章69 深度学习-异常值检测
开发语言·图像处理·算法·计算机视觉·c#
我是唐青枫22 分钟前
深入理解 C#.NET 运算符重载:语法、设计原则与最佳实践
开发语言·c#·.net
张np1 小时前
java基础-Deque 接口
java·开发语言