vs2019 16.8更新之后的 C++20 协程co_yield用法
由于搜索出来的帖子,都是老版本的实验协程,很多老的代码已经失去参考性,并且很复杂,所以就自己研究了一下。
1 #include <iostream>
2 #include <coroutine>
3 #include <thread>
4
5 template<typename _Ty>
6 struct cocontext {
7 struct promise_type;
8 using _Hty = std::coroutine_handle<promise_type>;
9 struct promise_type {
10 // 只要一个函数的返回值是 cocontext<T>,这个函数内存在co_await co_yield co_return这3个语法糖
11 // 就会第一时间调用 get_return_object
12 cocontext get_return_object() {
13 return { _Hty::from_promise(*this) };
14 }
15
16 // 协程异常时抛出到这里,关于异常,见仁见智,反正我是不用的。
17 void unhandled_exception() { std::terminate(); }
18
19 // co_await co_yield co_return 之前回调,只回调一次,它在get_return_object之后回调
20 auto initial_suspend() { return std::suspend_never{}; }
21
22 // 协程函数返回之后,回调这里
23 auto final_suspend() { return std::suspend_always{}; }
24
25 // 如果函数里没有co_return,必须实现return_void,与之相对的还有一个return_value,类似yield_value
26 void return_void() {}
27
28 // 如果函数里有co_yield,必须实现yield_value,这其实并不难理解,co_yield把数据传到参数,然后我储存在_Val里而已
29 auto yield_value(const _Ty &val) {
30 _Val = val;
31 return std::suspend_always{};
32 }
33 _Ty _Val;
34 };
35
36 // 如果 await_ready 返回true,它就会继续执行,所以理论上来说,要模拟异步场景,都只会是return false
37 bool await_ready() const{ return false; }
38
39 // await_suspend是可以有参数的,它还可以是 void await_suspend(std::coroutine_handle<cocontext> handle);
40 // 在co_await co_yield co_return时,首先会调用这里,也就是可以根据情况直接在这里进行handle.resume();
41 void await_suspend() {}
42
43 // 下面是我自己的实现
44 cocontext& resume() { if (!_Handle.done())_Handle.resume(); return *this; }
45 operator _Ty() const { return _Handle.promise()._Val; }
46
47 _Hty _Handle;
48 };
49
50 int main()
51 {
52 auto test = []()->cocontext<int> { for (int i = 0; i < 10; i++) co_yield i; };
53 auto c = test();
54 std::cout << (int)c << std::endl; // 0
55 std::cout << (int)c.resume() << std::endl; // 1
56 std::cout << (int)c.resume() << std::endl; // 2
57 std::cout << (int)c.resume() << std::endl; // 3
58 std::cout << (int)c.resume() << std::endl; // 4
59
60 std::thread([&]() {
61 // 协程真正有意思的地方是,它可以由不同的线程去resume,这会很有意义。
62 std::cout << (int)c.resume() << std::endl; // 5
63 std::cout << (int)c.resume() << std::endl; // 6
64 std::cout << (int)c.resume() << std::endl; // 7
65 std::cout << (int)c.resume() << std::endl; // 8
66 std::cout << (int)c.resume() << std::endl; // 9
67
68 // 这里依旧输出9,上面一个c.resume()之后,test函数已经跳出循环返回了,已经满足了_Handle.done(),不会再继续真正的_Handle.resume();
69 std::cout << (int)c.resume() << std::endl;
70 }).join();
71
72 }
73
74 /*
75 后话:
76 C++ 20所谓的协程,实际上在我看来,更像是语法糖内部包含了一堆回调函数
77 并且这些回调函数得让程序员自己去完全实现,这确实是C++的风格,
78 但说实在的,我相信搞得清楚这些东西的人,都不会太喜欢这种风格。
79
80 虽然我的例子中 cocontext是基本可重用的类型,但我依旧没感觉这种形式为我的程序带来了多少便利。
81 情况还是那个情况,这个东西用起来并不方便,程序员从一开始就要考虑到所有细节,
82 可能最终很多细节考虑之后,用起来还是一大堆代码,到时候可能写着写着把递归逻辑搞成线性逻辑了,然后感叹一句,“我是SB,我TM用个P的协程!”。
83 */
vs2019 16.8更新之后的 C++20 协程co_yield用法的更多相关文章
- C++20协程实例:携程化的IOCP服务端/客户端
VC支持协程已经有一段时间了,之前一直想不明白协程的意义在哪里,前几天拉屎的时候突然灵光一闪: 以下是伪代码: task server() { for (;;) { sock_context s = ...
- ubuntu 16.04 更新 gcc/g++ 4.9.2
ubuntu 转载 2016年10月12日 :: 标签:ubuntu /g++ /gcc [html] view plain copy sudo dpkg -l g++ 最近在学C++primer , ...
- python基础(16)-进程&线程&协程
进程之multiprocessing模块 Process(进程) Process模块是一个创建进程的模块,借助这个模块,就可以完成进程的创建. 介绍 初始化参数 Process([group [, t ...
- Python自动化运维之16、线程、进程、协程、queue队列
一.线程 1.什么是线程 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位. 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行 ...
- golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题
golang学习笔记20 一道考察对并发多协程操作一个共享变量的面试题 下面这个程序运行的能num结果是什么? package main import ( "fmt" " ...
- 【流畅的python】16.1 - 生成器如何进化成协程
在生成器中加入yield关键字后,生成器调用方可以向生成器传入值,只需要使用.send(...)方法就可以传送数据.发送的数据会成为生成器函数中yield表达式的值.所以生成器可以作为协程使用. 协程 ...
- python day 20: 线程池与协程,多进程TCP服务器
目录 python day 20: 线程池与协程 2. 线程 3. 进程 4. 协程:gevent模块,又叫微线程 5. 扩展 6. 自定义线程池 7. 实现多进程TCP服务器 8. 实现多线程TCP ...
- 比物理线程都好用的C++20的协程,你会用吗?
摘要:事件驱动(event driven)是一种常见的代码模型,其通常会有一个主循环(mainloop)不断的从队列中接收事件,然后分发给相应的函数/模块处理.常见使用事件驱动模型的软件包括图形用户界 ...
- linux_ubuntu 16.04 更新wifi驱动_无法链接wifi问题
ubuntu kylin ubuntu kylin ubuntu kylin wifi 这个很好解决的,16.04 默认 没有使用wifi驱动设备,默认选择的是:不使用设备1.进入到,软件和更新 -- ...
随机推荐
- STM32采集AD的输入阻抗问题
在做一款消费电子产品时,需要采集电池电压(3.3V-4.2V),同时在休眠的时候希望尽量减小待机电流.电池电压采集电路采用两个1%的300K电阻进行分压,由该电路引起的待机电路为4.2/(300+30 ...
- 外网访问vm虚拟机
目录 一.准备 二.外网访问主机电脑 三.外网访问VM虚拟机 一.准备 外网ip:39.189.8.5 访问https://www.ip138.com 可以查询外网ip 内网主机ip:192.168. ...
- Python AttributeError: module 'string' has no attribute 'atoi'
python2 中可以用string.atoi 在python3中会报错 替换的方案是 string.atoi(your_str) 替换为 int(your_str) 这个代码python2和pyth ...
- .NET 开源工作流: Slickflow流程引擎高级开发(九) -- 条件事件模式解释及应用
前言:在流程流转过程中,有时候需要条件模式的支持,这样可以使得流程流转更加灵活多变.比如在业务变量满足一定的条件时,可以启动特定配置的流程(或者位于主流程内部的子流程).本文主要描述条件启动和条件中间 ...
- Firefox火狐浏览器提示您的链接并不安全(解决办法)
火狐浏览器不管访问什么,一直提示连接不安全 解决办法: 1.在Firefox地址栏输入"about:config",回车,进入如下图页面 点击"我了解此风险" ...
- Solon & Solon Cloud 1.5.62 发布,轻量级 Java 基础开发框架
Solon 已有120个生态扩展插件,此次更新主要为细节打磨,且对k8s和docker-compose更友好: 1.插件 solon.coud ,事件总线增加支持本地同主题多订阅模式(以支持同服务内, ...
- 基于I2C的AHT20温湿度传感器的数据采集
关于:IC( Inter-- Integrated Circuit)总线是一种由 PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备.它是由数据线SDA和时钟SCL构成的串行总线,可 ...
- codeql初探
CodeQL初探 环境搭建 基于Windows 基于Mac 下载codeql https://github.com/github/codeql-cli-binaries/releases/latest ...
- S2-002漏洞分析
漏洞概述 Struts2-002是一个 XSS 漏洞,该漏洞发生在 <s:url> 和 <s:a>标签中,未对标签内字符进行转义,当标签的属性 includeParams=al ...
- Django 小实例S1 简易学生选课管理系统 3 创建用户模型(model)
Django 小实例S1 简易学生选课管理系统 第3节--创建用户模型(model) 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 本文涉及到的新 ...