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

news2025/1/18 20:07:19

目录

  • 1 协程
  • 2 实例
  • 3 运行

1 协程

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

2 实例

#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 运行

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1853162.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Interleaving Retrieval with Chain-of-Thought Reasoning for ... 论文阅读

Interleaving Retrieval with Chain-of-Thought Reasoning for Knowledge-Intensive Multi-Step Questions 论文阅读 文章目录 Interleaving Retrieval with Chain-of-Thought Reasoning for Knowledge-Intensive Multi-Step Questions 论文阅读 Abstract介绍相关工作开放域QA提…

Python+Pytest+Yaml+Request+Allure接口自动化测试框架详解

PythonPytestYamlAllure整体框架目录&#xff08;源代码请等下篇&#xff09; 框架详解 common:公共方法包 –get_path.py:获取文件路径方法 –logger_util.py:输出日志方法 –parameters_until.py&#xff1a;传参方式方法封装 –requests_util.py&#xff1a;请求方式方法封…

Cadence 16.6与17.4个人学习版推荐

一. 简介与下载 Cadence个人学习版是基于Cadence官方发行的安装包做了适当精简和优化的二次打包版本&#xff0c;包括了Cpature原理图设计、PSpice 电路仿真以及Allegro PCB设计等以电子产品设计为主的主要功能&#xff0c;能满足绝大部分硬件工程师的使用需求。 学习版预先已…

我国人工智能核心产业规模近6000亿元

以下文章来源&#xff1a;中国证券报 2024世界智能产业博览会6月20日至6月23日在天津举行。会上发布的《中国新一代人工智能科技产业发展报告2024》显示&#xff0c;我国人工智能企业数量已经超过4000家&#xff0c;人工智能已成为新一轮科技革命和产业变革的重要驱动力量和战略…

stm32学习笔记---OLED调试工具(理论部分和代码部分)

目录 理论部分 三种常用的程序调试方法 第一种是串口调试 第二种是显示屏调试 第三种是Keil调试模式 其他调试方式 OLED显示屏的介绍 OLED的硬件电路 OLED驱动程序中所包含的驱动函数 OLED_Init(); OLED_Clear(); OLED的显示函数 OLED_ShowChar(1, 1, A); OLED_S…

【SSM】

Spring常见面试题总结 Spring 基础 什么是 Spring 框架? Spring 是一款开源的轻量级 Java 开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。 我们一般说 Spring 框架指的都是 Spring Framework&#xff0c;它是很多模块的集合&#xff0c;使用这些模块…

海洋生物识别系统+图像识别+Python+人工智能课设+深度学习+卷积神经网络算法+TensorFlow

一、介绍 海洋生物识别系统。以Python作为主要编程语言&#xff0c;通过TensorFlow搭建ResNet50卷积神经网络算法&#xff0c;通过对22种常见的海洋生物&#xff08;‘蛤蜊’, ‘珊瑚’, ‘螃蟹’, ‘海豚’, ‘鳗鱼’, ‘水母’, ‘龙虾’, ‘海蛞蝓’, ‘章鱼’, ‘水獭’, …

计算机系统基础实训五—CacheLab实验

实验目的与要求 1、让学生更好地应用程序性能的优化方法&#xff1b; 2、让学生更好地理解存储器层次结构在程序运行过程中所起的重要作用&#xff1b; 3、让学生更好地理解高速缓存对程序性能的影响&#xff1b; 实验原理与内容 本实验将帮助您了解缓存对C程序性能的影响…

地推利器Xinstall:全方位二维码统计,打造高效地推策略,轻松掌握市场脉搏!

在移动互联网时代&#xff0c;地推作为一种传统的推广方式&#xff0c;依然占据着重要的地位。然而&#xff0c;随着市场竞争的加剧&#xff0c;地推也面临着诸多挑战&#xff0c;如如何有效监测下载来源、解决填码和人工登记的繁琐、避免重复打包和iOS限制、以及如何准确考核推…

安装vue时候发现npm淘宝镜像不能使用,报出:npm.taobao.org和registry.npm.taobao.or

2024.3.12 安装vue时候发现npm淘宝镜像不能使用&#xff0c;需要重新更换源&#xff0c;简单来说就是更换镜像 使用 npm config get registry 查看当前的镜像&#xff1b; npm config get registry 使用npm config set registry http://mirrors.cloud.tencent.com/npm/ &…

嵌入式实验---实验五 串口数据接收实验

一、实验目的 1、掌握STM32F103串口数据接收程序设计流程&#xff1b; 2、熟悉STM32固件库的基本使用。 二、实验原理 1、STM32F103R6能通过查询中断方式接收数据&#xff0c;每接收到一个字节&#xff0c;立即向对方发送一个相同内容的字节&#xff0c;并把该字节的十六进…

见证数据的视觉奇迹——DataV Atlas

引言 前段时间一直沉迷于AI方向&#xff0c;几乎很久没碰大数据开发的相关内容了&#xff0c;今天突然看到阿里活动又推出DataV的体验了&#xff0c;我直接“啪”的一下就点进来了&#xff0c;很快啊&#xff01;本来之前开发数字孪生的时候就接触过基础的DataV操作了&#x…

Monica

在 《long long ago》中&#xff0c;我论述了on是一个刚出生的孩子的脐带连接在其肚子g上的形象&#xff0c;脐带就是long的字母l和字母n&#xff0c;l表脐带很长&#xff0c;n表脐带曲转冗余和连接之性&#xff0c;on表一&#xff0c;是孩子刚诞生的意思&#xff0c;o是身体&a…

Redis 的安装与部署

本文为Redis的Linux版单机部署。 上传 redis-3.2.8 源码到 /opt/software/ 解压到 /opt/module/ [huweihadoop101 software]$ tar -zxvf redis-3.2.8.tar.gz -C /opt/module/安装依赖 [huweihadoop101 software]$ sudo yum -y install gcc-c tclRedis是C语言编写的 编译安装…

文件顺序读取--函数解析

fgetc和fputc 函数 fgetc和fputc是C语言中用于文件操作的函数&#xff0c;分别用于从文件中读取字符和向文件中写入字符。以下是这两个函数的详细原型和说明&#xff1a; fgetc函数原型 int fgetc(FILE *stream);参数说明&#xff1a; FILE *stream&#xff1a;一个指向FIL…

【Linux系列】find命令使用与用法详解

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

淘酒屋荣获2024中法贸易杰出服务商称号暨夏季窖主大会圆满召开

淘酒屋荣获中法贸易杰出服务商称号&#xff0c;暨闪光的创始人2024夏季窖主大会圆满召开 2024年&#xff0c;作为中法建交60周年的重要节点&#xff0c;同时迎来了中法文化旅游年&#xff0c;这为两国文化交流与合作开启了新的篇章。在庆祝中法贸易交流的重要时刻&#xff0c;…

Java——集合(一)

前言: Collection集合&#xff0c;List集合 文章目录 一、Collection 集合1.1 集合和数组的区别1.2 集合框架1.3 Collection 集合常用方法1.4 Collction 集合的遍历 二、List 集合2.1 List 概述2.2 List集合的五种遍历方式2.3 List集合的实现类 一、Collection 集合 1.1 集合和…

ubuntu 18.04 server源码编译安装freeswitch 1.10.11——筑梦之路

前言 这里主要编译支持语音通话、视频通话、短信、webrtc功能的PBX。 安装编译工具包和依赖包 sudo apt-get updatesudo apt-get install -y autoconf git libtool g zlib1g-dev libjpeg-dev libcurl4-openssl-dev libspeex-dev libldns-dev libedit-dev libssl-dev pkg-con…

学校报修管理系统

摘 要 随着社会的发展和技术的进步&#xff0c;学校报修管理系统在学校设备维修工作中扮演着至关重要的角色。该系统的设计和实现对于提高学校设备维修效率、优化资源管理、提升用户体验具有重要意义。本论文基于SpringBoot框架&#xff0c;设计并实现了一套学校报修管理系统。…