Coke(五):协程任务的同步/异步等待

项目Github主页Coke。

在前几篇文章中,多次用到了协程任务上的同步等待和异步等待功能,本文将对这部分内容做进一步的介绍。首先来看一个简单的例子

#include <iostream>
#include <chrono>
#include "coke/coke.h"coke::Task<int> prepare() {int ms = 100;int ret;ret = co_await coke::sleep(std::chrono::milliseconds(ms));if (ret != coke::STATE_SUCCESS)co_return ret;// do something elseco_return co_await coke::sleep(std::chrono::milliseconds(ms));
}coke::Task<void> hello() {int ret;ret = co_await prepare(100);if (ret == coke::STATE_SUCCESS)std::cout << "Hello world" << std::endl;
}int main() {coke::sync_wait(hello());return 0;
}

在这个例子中,main是我们经常会见到的C++函数,而hello则是一个协程,在C++协程中,使用co_await来实现对可等待体的异步等待。在hello协程中,先展示了如何使用co_await异步等待prepare协程并获取其返回值,然后再输出Hello world

coke::Task<T>是满足C++ 20协程约束的类型,在coke中,返回coke::Task<T>且使用了co_awaitco_return的函数是一个协程,而T则是协程运行完成后的返回值。由于本文只是介绍coke的使用方法,不会深入介绍协程的太多概念,如果此前未从了解过协程,请一定避免陷入“必须先完全搞懂底层机制再学如何使用”的泥淖,就像小学教加法交换律前不会教阿贝尔群的概念一样,先把简单的用法搞起来,以后有的是机会了解机制。

看到这里,熟悉C++ Workflow的读者可以感受到:coke中的协程与workflow中的串行(SeriesWork)很相似,都是将一组异步任务串起来逐个执行的组件;而coke::sleepWFTimerTask很相似,都是用来完成特定任务的基础组件。但隐约感觉还少一个组件:并行(ParallelWork)。令人惊喜的是,在协程中组织任务的方式非常直观和灵活,无需复杂的机制来实现并行,而是提供了方便的coke::async_wait接口,只需要将一组任务交给它即可实现并行。

#include <iostream>
#include <chrono>
#include <vector>
#include "coke/coke.h"coke::Task<int> sleep(int ms) {int ret = co_await coke::sleep(std::chrono::milliseconds(ms));co_return ret;
}coke::Task<> parallel(int n) {std::vector<coke::Task<int>> tasks;tasks.reserve(n);for (int i = 0; i < n; i++)tasks.emplace_back(sleep(100));std::vector<int> rets;rets = co_await coke::async_wait(std::move(tasks));std::cout << "Parallel done" << std::endl;
}int main() {coke::sync_wait(parallel(6));return 0;
}

细心的读者会发现其中一个瑕疵,只有具有相同返回值的协程才能被传递给coke::async_wait,这并不是因为技术或语言上的限制,而是不希望通过一系列奇技淫巧搞出来一个语法怪兽,令人难以读懂和正确使用。对于真的有这种需求的场景,目前可以通过封装成无返回值(coke::Task<void>)的协程来实现。

对于同步等待,几乎每个示例代码都会看到coke::sync_wait,毕竟C++的函数入口目前还是同步方式,必然需要同步机制来等待协程运行完成。对于同步等待的使用方式,作者认为只需要常见的这一种即可,通过这种方式启动一个协程,其他所有的操作都以异步等待的方式实现,并牢记“仅在同步函数中使用同步等待,仅在协程中使用异步等待”。coke认为所有使用者都是聪慧的,所以不会采取任何措施来避免线程都被同步等待阻塞的情况。

本系列文章同步发布于个人网站和知乎专栏,转载请注明来源,以便读者及时获取最新内容及勘误。

附录:目前支持的所有同步/异步等待方法

#include <iostream>
#include <chrono>
#include <vector>
#include "coke/coke.h"coke::Task<int> sleep(int ms) {int ret = co_await coke::sleep(std::chrono::milliseconds(ms));co_return ret;
}int func() {return 1;
}void sync_wait_example() {int ret;std::vector<int> vret;// 1. 等待单个coke::Taskret = coke::sync_wait(sleep(100));std::cout << "sync wait one coke::Task " << ret << std::endl;// 2. 等待多个coke::Taskstd::vector<coke::Task<int>> tasks;for (int i = 0; i < 3; i++) {tasks.emplace_back(sleep(100));}vret = coke::sync_wait(std::move(tasks));std::cout << "sync wait multi coke::Task\n";// 3. 等待多个coke::Task,语法糖,适用于任务数量确定的情况vret = coke::sync_wait(sleep(100), sleep(100));std::cout << "sync wait multi coke::Task\n";// 4. 等待单个coke::*Awaiterret = coke::sync_wait(coke::sleep(std::chrono::milliseconds(100)));std::cout << "sync wait one SleepAwaiter " << ret << std::endl;// 5. 等待多个相同类型的coke::*Awaiterstd::vector<coke::SleepAwaiter> awaiters;for (int i = 0; i < 3; i++)awaiters.emplace_back(coke::sleep(std::chrono::milliseconds(100)));vret = coke::sync_wait(std::move(awaiters));std::cout << "sync wait multi SleepAwaiters\n";// 6. 等待多个返回值相同的coke::*Awaitervret = coke::sync_wait(coke::sleep(std::chrono::milliseconds(100)),coke::go(func));std::cout << "sync wait multi Awaiters\n";
}coke::Task<> async_wait_example() {int ret;std::vector<int> vret;// 1. 等待单个coke::Taskret = co_await sleep(100);std::cout << "async wait one coke::Task " << ret << std::endl;// 2. 等待多个coke::Taskstd::vector<coke::Task<int>> tasks;for (int i = 0; i < 3; i++) {tasks.emplace_back(sleep(100));}vret = co_await coke::async_wait(std::move(tasks));std::cout << "async wait multi coke::Task\n";// 3. 等待多个coke::Task,语法糖,适用于任务数量确定的情况vret = co_await coke::async_wait(sleep(100), sleep(100));std::cout << "async wait multi coke::Task\n";// 4. 等待单个coke::*Awaiterret = co_await coke::sleep(std::chrono::milliseconds(100));std::cout << "async wait one SleepAwaiter " << ret << std::endl;// 5. 等待多个相同类型的coke::*Awaiterstd::vector<coke::SleepAwaiter> awaiters;for (int i = 0; i < 3; i++)awaiters.emplace_back(coke::sleep(std::chrono::milliseconds(100)));vret = co_await coke::async_wait(std::move(awaiters));std::cout << "async wait multi SleepAwaiters\n";// 6. 等待多个返回值相同的coke::*Awaitervret = co_await coke::async_wait(coke::sleep(std::chrono::milliseconds(100)),coke::go(func));std::cout << "async wait multi Awaiters\n";
}int main() {sync_wait_example();coke::sync_wait(async_wait_example());return 0;
}

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

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

相关文章

linux espidf vscode

安装 根据 https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32s2/get-started/linux-macos-setup.html 里的要求安装一些东西&#xff0c;点插件的首页的“… Package”也能跳转 在 vscode 里安装 ESP-IDF 插件&#xff0c;下载服务器选择 Espressif&#xff0c…

我眼中的大数据: 我们未来该往何处

满打满算&#xff0c;工作接近三年的时间了&#xff0c;入行大数据也三年了。从开始时惊艳于大数据处理的高效&#xff0c;到现在时常迷茫未来数据的出路在哪&#xff0c;恍恍惚惚跨过了互联网的高峰。今天突然觉得&#xff0c;该总结下过去&#xff0c;思考下未来。我尽可能少…

自动化控制系统的设计重点是什么?

要实现对选择性激光烧结系统预热温度的控制&#xff0c;需要找到合理的控制对象模型&#xff0c;但选择性激光烧结设备的预热温度场是一个复杂的非线性系统&#xff0c;很难找到合理的控制对象模型来实现预热温度场的温度控制。模糊控制不需要具体的控制模型&#xff0c;预热温…

3ds max文件打包?max插件CG Magic一键打包整起!

3ds max文件如何打包&#xff1f;这个问题&#xff0c;小编听到不少网友的提问&#xff01; 今天CG Magic小编来和大家聊聊&#xff0c;文件更高效的操作&#xff0c;如何打包处理呢&#xff1f; 3DMAX这款软件的受众群体是比较高的&#xff0c;在工作方便的同时&#xff0c;…

系统架构设计高级技能 · 构件与中间件技术

点击进入系列文章目录 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reality. 系统架构设计高级技能 构件与中间件技术 一、构件的定义二、构件系统架构特性三…

电脑大文件删除了能恢复吗 电脑大文件删除了怎么恢复

在日常办公中&#xff0c;电脑是必不可少的办公工具&#xff0c;电脑能够帮助我们储存大量的大文件&#xff0c;但是有时候可能会因为一些误操作或者电脑故障等情况&#xff0c;导致一些电脑大文件的丢失&#xff0c;所以今天就和大家分享一下&#xff0c;电脑大文件删除了能恢…

jmeter采集ELK平台海量业务日志( 采用Scroll)

由于性能测试需要&#xff0c;需采集某业务系统海量日志&#xff08;百万以上&#xff09;来使用。但Elasticsearch的结果分页size单次最大为10000&#xff08;运维同事为保证ES安全&#xff09;。为了能够快速采集ELK平台业务日志&#xff0c;可以使用以下2种方式采集&#xf…

Ubuntu下高效Vim的搭建(离线版)

软件界面 可以看到界面下方有一些常用提示信息&#xff1a;文件路径、format、文件类型、光标所在的坐标(x,y)、进度条(百分比)、日期时间 会提示已定义的变量名词(快速补全) 搭建方法 下载资源文件 把Vim 和 .vimrc 拷贝到家目录下&#xff0c;并执行tar -xvf Vim 即可。 …

Leetcode 2850. Minimum Moves to Spread Stones Over Grid

Leetcode 2850. Minimum Moves to Spread Stones Over Grid 1. 算法思路2. 代码实现 题目链接&#xff1a;2850. Minimum Moves to Spread Stones Over Grid 1. 算法思路 这一题由于棋盘比较小&#xff0c;只是一个3x3的棋盘&#xff0c;所有的移动策略总量有限&#xff0c;…

社区团购商城小程序v18.1开源独立版+前端

新增后台清理缓存功能 修复定位权限 修复无法删除手机端管理员 11月新登录接口修复&#xff01; 修复商家付款到零钱&#xff0c; 修复会员登陆不显示头像&#xff0c; 修复无法修改会员开添加绑定

uniapp项目实践总结(十五)使用websocket实现简易聊天室

导语:在一些社交软件中,经常可以看到各种聊天室的界面,接下来就总结一下聊天室的原理个实现方法,最后做一个简易的聊天室,包括登录/登出、加入/离开房间、发送接收聊天消息等功能。 目录 准备工作原理分析组件实现实战演练服务端搭建案例展示准备工作 在pages/index文件夹…

【微信小程序】网络请求

环境&#xff1a;微信小程序开发工具 测试api&#xff08;随机获取猫咪靓照&#xff09;:https://api.thecatapi.com/v1/images/search?limit2 示例&#xff1a; 完整代码 request.wxml <button bind:tap"requestBtn" type"primary">网络请求&l…

javascript获取元素在浏览器中工作区域的左、右、上、下距离,或带滚动条的元素在页面中的大小

//获取元素在包含元素框中的大小 //第1个函数为获取元素在包含元素中左内边框的距离 function getELementLeft(element){//获取元素在包含元素左边距离var actualeftelement.offsetLeft;//获取元素的上级包含元素var currentelement.offsetParent;//循环到一直没有包含元素whil…

Otter改造 增加springboot模块和HTTP调用功能

环境搭建 & 打包 环境搭建&#xff1a; 进入 $otter_home/lib 目录执行&#xff1a;bash install.sh 打包&#xff1a; 进入$otter_home目录执行&#xff1a;mvn clean install -Dmaven.test.skip -Denvrelease发布包位置&#xff1a;$otter_home/target 项目背景 阿里…

【小沐学CAD】嵌入式UI开发工具:GL Studio

文章目录 1、简介2、软件功能3、应用行业3.1 航空3.2 汽车3.3 防御3.4 工业3.5 电力与能源3.6 医疗3.7 空间3.8 科技 结语 1、简介 https://disti.com/gl-studio/ DiSTI 是 HMI 软件、虚拟驾驶舱、仪表、信息娱乐、集群显示器和嵌入式 UI 解决方案的领先提供商。 而它的GL Stu…

React如何实现国际化?

目录 一、Redux准备工作 commonTypes.js commonActions.js commonReducer.js rootReducer.js 二、然后定义SelectLang组件 index.js index.less 三、创建语言包 welcomeLocale.js index.js 四、使用 react的入口文件 App.js welcome.js 附 关于如何实现国际…

OpenCV项目实战(2)— 如何用OpenCV实现弹球动画

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。OpenCV能够在画布上绘制静态的图形&#xff0c;例如&#xff0c;线段、矩形、正方形、圆形、多边形、文字等。那么&#xff0c;能不能让这些静态的图形移动起来&#xff1f;如果能&#xff0c;又该如何编写代码呢&#xff…

论文总结《A Closer Look at Few-shot Classification Again》

原文链接 A Closer Look at Few-shot Classification Again 摘要 这篇文章主要探讨了在少样本图像分类问题中&#xff0c;training algorithm 和 adaptation algorithm的相关性问题。给出了training algorithm和adaptation algorithm是完全不想关的&#xff0c;这意味着我们…

Day46:项目-购物车案例

购物车案例 准备工作 首页默认加载&#xff0c;其余页面懒加载 调用defineStore方法构建store 入口main做对应配置&#xff0c;找指南&#xff0c;快速开始&#xff0c;把elementplus引入进来 import { createApp } from "vue"; import { createPinia } from &qu…

典型数据结构-栈/队列/链表、哈希查找、二叉树(BT)、线索二叉树、二叉排序树(BST树)、平衡二叉树(AVL树)、红黑树(RB树)

目录 典型数据结构列举 栈/队列/链表 树 二叉树 线索二叉树 二叉排序树 平衡二叉树&#xff08;AVL树&#xff09; 红黑树 其它树种和应用介绍 典型数据结构列举 栈/队列/链表 描述略。 一些基本的简单实现参考/数据结构简单实现/文件夹里面。 线性表详解&#xff…