2308C++简单异步懒
Lazy
Lazy
由C++20
无栈协程实现.一个Lazy
闭包一个懒求值的计算任务
.
使用Lazy
想用Lazy
,需要先#inlude<async_simple/coro/Lazy.h>
,再实现返回类型为Lazy<T>
的协程函数即可.如:
# 包含<简单异步/协程/懒.h>懒<整>任务1(整 x){协中 x;//带有`协中`的函数是协程函数.
}
在Lazy
中也可协待
其他可等待
对象:
# 包含<简单异步/协程/懒.h>
懒<整>任务2(整 x){协待 标::总是挂起{};协中 x;
}
启动方式
一个Lazy
应该以协待
,同步等待
及.start(回调)
方式启动.
协待
启动
如:
# 包含<简单异步/协程/懒.h>
懒<整>任务1(整 x){协中 x;
}
懒<>任务2(){动 t=任务1(10);动 x=协待 t;//开始执行t协程断定(x==10);
}
协待
的Lazy
时会触发对称变换
,它会挂起
当前协程并立即执行协待
的Lazy
.执行完协待
的Lazy
后,会使用对称变换
来唤醒当前挂起的协程
.
并按协待
式的值返回Lazy<T>
中所包含的值.
需要注意,协待
一个Lazy
时并不能假设一定会执行协待
后的语句.原因如:
1,未完成等待的任务.
2,分发器实现有bug
,最后不一定会执行了提交
到分发器的任务.
3,执行等待任务过程中出现了异常
,此时协待
会直接返回该异常
到当前正在等待的Lazy
,而不会执行之后的语句了.
同时需要注意,使用协待
启动Lazy
需要当前函数也为C++20
无栈协程.
.start
(回调)启动
如:
# 包含<简单异步/协程/懒.h>
# 包含<io流>
懒<整>任务1(整 x){协中 x;
}
懒<>任务2(){动 t=任务1(10);动 x=协待 t;断定(x==10);
}
空 函数(){任务2().开始([](试<空>结果){如(结果.有错误())标::输出<<"任务2错误.\n";异标::输出<<"任务2成功.\n";});
}
Lazy<T>::start(回调)
中的回调
需要是一个接受Try<T>
类型参数的callable
对象.
调用Lazy<T>::start(回调)
方法后,会立即开始执行Lazy
,并在Lazy
执行完成后,把Lazy
的结果传入回调
中执行.
在设计上,start
是非阻塞
异步调用接口.语义上,用户可认为调用start
后立即返回.用户不应假设调用start
后会何时返回.这是由Lazy
的执行情况决定的.
对不需要回调
的情况,用户可写:
任务().开始([](动&&){});
同步等待
启动
如:
# 包含<简单异步/协程/懒.h>
懒<整>任务1(整 x){协中 x;
}
懒<>任务2(){动 t=任务1(10);动 x=协待 t;断定(x==10);
}
空 函数(){动 值=同步等待(任务2());//同步等待,执行完任务2
}
在启动Lazy
的同时,同步等待
会阻塞
当前进程直到执行完同步等待
的Lazy
.同步等待
属于同步阻塞.
取值与异常处理
对Lazy<T>
类型的任务
对象,协待任务
的返回类型为T
.如果执行任务
过程中有异常,则协待任务
会直接抛该异常.
如:
懒<整>福(){抛 标::运行时错误("测试");协中 1;
}
懒<整>条(){整 资源;试{资源=协待 福();}抓(...){标::输出<<"福有错.置结果为-1.\n";资源=-1;}协中 资源;
}
空 栏(){动 资源=同步等待(条());标::输出<<"结果:"<<资源<<"\n";//资源 的值会是-1.
}
需要注意,虽然协待任务
时有可能会抛异常,但总是使用try...catch
包装协待
并不是推荐的做法.一方面这样写确实很麻烦,另一方面,当协待
抛异常时,协程的框架保证了会由协待
所在的协程
处理抛的异常.
如:
懒<整>福(){抛 标::运行时错误("测试");协中1;
}
懒<整>条(){整 资源;资源=协待 福();断定(假);//不会执行,因为上一行会抛异常.协中 资源;
}
懒<整>栏(){协中 协待 条();
}
空 正常(){试{同步等待(栏());}抓(...){//可在此抓到异常.}
}
空 正常2(){栏().开始([](试<整>结果){如(结果.有错误())标::输出<<"栏有错误!!\n";});
}
当由协待
组成的任务链的某一层出现异常时,异常会一层层地往上抛.对同步等待
形式的启动方式,可在同步等待
处加上try..catch
语句.而对实际中更常用的.start
方式,可在回调处通过Try
对象取是否出现异常.
如果不想让异常
直接往上抛,而想直接处理,则可用coAwaitTry
接口.如:
懒<整>福(){抛 标::运行时错误("测试");协中 1;
}
懒<整>条(){试<整>资源=协待 福().试协待();如(资源.有错误()){标::异常针 错误=资源.取异常();//计算错误}协中 资源.值();
}
对Lazy<T>
类型的对象任务
,协待任务.coAwaitTry()
的返回值类型为Try<T>
.
调度懒
调度懒
在语义上是绑定了Executor
的Lazy
.调度懒
在协待 Lazy
时并不会使用对称变换
立即执行Lazy
,而是唤醒Lazy
的任务,并提交它到调度懒
绑定的Executor
中.因为语义上调度懒
也是Lazy
,所以调度懒
也能使用Lazy
的协待
,.start
和同步等待
接口.
创建调度懒
不能直接创建调度懒
,也不能像Lazy
一样作为协程的返回类型.只能通过Lazy
的via
接口创建调度懒
,如:
空 福(){执行器::简单执行器 e1(1);动 加一=[&](整 x)->懒<整>{动 临=协待 取值(x);协中 临+2;};再安排懒 分发=加一().通过(&e1);同步等待(分发);//由分发器决定何时开始`加一`的执行
}
分发器的传递
在编写计算任务时,都只使用Lazy
.当想要为一个计算任务指定分发器时,只需要在任务开始阶段指定分发器即可.
指定的分发器会随着协待
一路传递下去.
如:
# 包含<简单异步/协程/懒.h>
# 包含<io流>
懒<整>任务1(整 x){协中 协待 计算(x);
}
懒<整>任务2(整 x){协中 协待 任务1(x);
}
懒<整>任务3(整 x){协中 协待 任务2(x);
}
懒<整>任务4(整 x){协中 协待 任务3(x);
}
空 函数(整 x,执行器*e){任务4(x).通过(e).开始([](动&&结果){标::输出<<"完成计算x的任务.\n结果是"<<结果<<"\n";});
}
在上例中,任务1...任务4
转发计算任务的调用链,其结果都是以Lazy
表示的.
在func
中,在创建了任务4
的Lazy
后,为其指定了分发器e
得到了一个调度懒
.
之后调用.start
时,不仅任务4
具体何时执行是由分发器决定的.
包括任务3
,任务2
,任务1
何时执行,也都是由分发器决定的.
总之,当需要为多个Lazy
组成的任务链指定分发器时,只需要在任务链的开头指定分发器就好了.
Collect
collectAll
当有多个计算任务时,一个很常见需求是等待
所有计算任务完成以取所有任务的结果后再进一步
的计算.
可用collectAll
接口完成该需求.如:
懒<整>福(){标::向量<懒<整>>输入;输入.压后(计算任务(1));输入.压后(计算任务(2));向量<试<整>>出=协待 收集所有(标::移动(输入));协中 出[0].值()+出[1].值();
}
collectAll
表示开始执行参数中所有Lazy
的任务.collectAll
是一个协程
,要用协待
以取结果.
参数要求
collectAll
接受两类的参数:
1,参数类型:std::vector<Lazy<T>>
.返回类型:std::vector<Try<T>>
.
2,参数类型:Lazy<T1>,Lazy<T2>,Lazy<T3>,...
.返回类型:std::tuple<Try<T1>,Try<T2>,Try<T3>,...>
.
第二个参数类型的示例为:
懒<整>计算整();
懒<双精>计算双精();
懒<标::串>计算串();
懒<>福(){标::元组<试<整>,试<双精>,试<标::串>>资源=协待 收集所有(计算整(),计算双精(),计算串());试<整>整资源=标::取<0>(资源);如(整资源.有错误())标::输出<<"计算整()时,错误\n";异标::输出<<"计算整结果为:"<<整资源.值()<<"\n";//...
}
其他接口
collectAllPara
如果colletAll
的所有参数都是Lazy
而非调度懒
,则collectAll
会单线程地执行每个Lazy
.
有两个办法:
1,为所以参数绑定Lazy
使其成为调度懒
.
2,使用collectAllPara
.
使用collectAllPara
需要注意其所在协程必须要绑定分发器,否则依然是单线程执行所有Lazy
.
如:
懒<整>福(){标::向量<懒<整>>输入;输入.压后(计算任务(1));输入.压后(计算任务(2));向量<试<整>>出=协待 收集所有段(标::移动(输入));协中 出[0].值()+出[1].值();
}
空 条(){//动 t=同步等待(福());//错误!福()没有绑定分发器!依然会串行执行.执行器::简单执行器 e1(1);动 t=同步等待(福().通过(&e1));//正确,提前为 福()绑定分发器
}
collectAllPara
的参数与返回类型和collectAll
相同.
collectAllWindowed
当需要分批次的执行并发任务时,可用collectAllWindowed
.
collectAllWindowed
的参数列表及语义为为:
1,size_t maxConcurrency
.每个批次所规定的任务数.
2,bool yield
.在执行完当前批次后,是否需要yield
使当前协程退出,把控制权交给其他协程.
3,std::vector<Lazy<T>>lazys
.所有需要执行的任务.
如:
懒<整>和(标::向量<试<整>>输入);
懒<整>批量求和(大小型 总数,大小型 批大小){标::向量<懒<整>>输入;对(动 i=0;i<总数;i++)输入.压后(计算任务());动 出=协待 收集所有窗口(批大小,真,标::移动(输入));协中 协待 和(标::移动(出));
}
collectAny
只需要等待所有计算任务中的任意一个
任务完成时,可用collectAny
来取第一个
完成的任务结果.此时会忽略
其他尚未完成任务的结果.
collectAny
接受的参数为std::vector<Lazy<T>>
.返回类型为Lazy<CollectAnyResult<T>>
.
CollectAnyResult
的数据结构为:
元<型名 T>
构 收集任一结果<空>{大小型 _索引;试<T> _值;
};
其中_idx
表示第一个完成的任务的编号,_value
表示第一个完成的任务的值.
如:
懒<空>福(){标::向量<懒<整>>输入;输入.压后(计算任务(1));输入.压后(计算任务(2));动 结果=协待 收集任一(标::移动(输入));标::输出<<"第1任务索引为"<<结果._索引<<"\n";如(结果._值.有错误())标::输出<<"失败了.\n";异标::输出<<"结果:"<<结果._值.值()<<"\n";
}
相关文章:
2308C++简单异步懒
Lazy Lazy由C20无栈协程实现.一个Lazy闭包一个懒求值的计算任务. 使用Lazy 想用Lazy,需要先#inlude<async_simple/coro/Lazy.h>,再实现返回类型为Lazy<T>的协程函数即可.如: # 包含<简单异步/协程/懒.h>懒<整>任务1(整 x){协中 x;//带有协中的函数…...

Linux常规操作命令
日升时奋斗,日落时自省 目录 1、vim 1.1、工作模式 1.2、末行模式操作相关命令 1.2.1、保存退出操作 1.2.2、查找替换 1.3、输入模式操作相关命令 1.3.1、移动相关命令 1.3.2、删除和剪切命令 1.3.3、复制操作 1.3.4、撤销 2、head 3、tail 4、ps 5、…...

日期切换
组件:<template><div class"time-picker"><el-radio-group size"small" v-model"timeType" change"changePickerType"><el-radio-button label"hour" v-if"isShow">时</el…...

怎么裁剪视频大小尺寸?简单的裁剪方法分享
怎么裁剪视频的画面大小尺寸呢?有时当我们下载下来一段视频,由于视频的画面大小比例不同,会有很多的黑边,我们不管是观看还是进行二次编辑都非常影响体验,而调整视频画面比例以适应观众的设备或平台,比如将…...

智慧工地源码,Spring Cloud+ Vue+UniApp开发,微服务架构
智慧工地源码,智慧工地云平台源码 智慧工地APP源码 智慧工地的核心是数字化,它通过传感器、监控设备、智能终端等技术手段,实现对工地各个环节的实时数据采集和传输,如环境温度、湿度、噪音等数据信息,将数据汇集到云…...

【Hystrix技术指南】(5)Command创建和执行实现
创建流程 构建HystrixCommand或者HystrixObservableCommand对象 *使用Hystrix的第一步是创建一个HystrixCommand或者HystrixObservableCommand对象来表示你需要发给依赖服务的请求。 若只期望依赖服务每次返回单一的回应,按如下方式构造一个HystrixCommand即可&a…...

学习笔记-JAVAJVM-JVM的基本结构及概念
申明:文章内容是本人学习极客时间课程所写,文字和图片基本来源于课程资料,在某些地方会插入一点自己的理解,未用于商业用途,侵删。 原资料地址:课程资料 什么是JVM 原文连接: 原文连接 JVM是J…...

ubuntu20.04 docker 下编译 tensorflow-gpu
ubuntu20.04 安装tensorflow-gpu 配置: 系统 ubuntu 20.04 LTS 显卡 GTX 1060 6G 1 安装cudatoolkit (我选 CUDA Toolkit 12.2 ) NVIDIA CUDA Installation Guide for Linux https://docs.nvidia.com/cuda/cuda-installation-guide-linux/in…...

❤ VUE3 项目路由拦截器配置(二)
❤ VUE3 项目 路由拦截器进一步 配置 路由拦截抽离为单个模块permission.ts 路由配置规则 白名单(直接进入) PC页面和PC子页面(直接进入) 后台页面(验证token ) 没有token> 后台登录页面 有token> 后…...
Filament 如何自定义登录页面
官方的页面太简约了,而且可供修改的范围太少了 通过发布官方资源可以看到 resources/views/vendor/filament-panels/pages/auth/login.blade.php <x-filament-panels::page.simple>if (filament()->hasRegistration())<x-slot name"subheading&…...

百度智能云“千帆大模型平台”最新升级:接入Llama 2等33个模型!
今年3月,百度智能云推出“千帆大模型平台”。作为全球首个一站式的企业级大模型平台,千帆不但提供包括文心一言在内的大模型服务及第三方大模型服务,还提供大模型开发和应用的整套工具链,能够帮助企业解决大模型开发和应用过程中的…...

[保研/考研机试] KY129 简单计算器 浙江大学复试上机题 C++实现
描述 读入一个只包含 , -, *, / 的非负整数计算表达式,计算该表达式的值。 输入描述: 测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中…...

推出 Elasticsearch 查询语言 (ES|QL)
作者:Costin Leau 我很高兴地宣布,经过大约一年的开发,Elasticsearch 查询语言 (ES|QL) 已准备好与世界共享,并已登陆 Elasticsearch 存储库。 ES|QL 是 Elasticsearch 原生的强大声明性语言,专为可组合性、表现力和速…...

机器学习 day32(神经网络如何解决高方差和高偏差)
解决高偏差和高方差的新方法 之前,我们需要通过选取多项式次数以及正则化参数λ,来平衡高方差和高偏差 只要训练集不是特别大,那么一个大型的神经网络总能很好的适应训练集,即它的Jtrain很低由此可以得出,若要减小Jt…...

Web前端之NodeJS、Vue
文章目录 一、Babel转码器1.1 Babel安装流程1.2 Babel命令行转码 二、Promise对象三、测试方式四、Vue(渐进式JS框架)4.1 准备4.2 创建一个项目4.3 运行一个项目 五、模板语法5.1 文本5.2 原始html5.3 属性Attribute5.4 使用JavaScript表达式 六、条件渲…...

冠达管理:银行定增是利好还是利空?
银行定增是指银行经过向特定投资者定向发行股票的方法进行增发。这种方法被认为可认为银行提供本钱充足、拓展融资渠道、增强抵挡危险的才能。但是,关于银行定增是否对商场和投资者带来积极影响的讨论一向存在。本文将从多个角度进行剖析,以讨论银行定增…...
背上小书包准备run之TypeScript篇
这TypeScript我真不知道面试会咋问。。。 哦以前还写过一篇基础⬇️ Typescript 基础易理解-------冲冲冲_ts和js有什么区别_慢谷的博客-CSDN博客 typescript是啥?与javascript的区别? TypeScript是一个强类型的JavaScript超集,可编译为纯…...

什么是绩效管理?绩效管理包括哪些内容?
阅读本文您可以了解:1、绩效管理的定义;2、绩效管理的内容; 一、什么是绩效管理 绩效管理是一种组织和管理方法,旨在确保员工的工作与组织的目标保持一致,以及激励和提高员工的工作表现。它涉及设定明确的目标和标准&…...

Java基础练习八(二维数组)
1.装水问题 有一个 异形 容器,用一个 n * n 的二维数组来表示。其中 1 表示容器实心部分, 0 表示空心部分。现使用此容器装水,能装多少水(每个元素都表示一份水,只有有挡板的部分能装水)? publi…...
Biopython序列比对
从InterPro网站(https://www.ebi.ac.uk/interpro/download/Pfam/)下载多序列比对文件Pfam-A.seed.gz(含多个多序列比对) wget https://ftp.ebi.ac.uk/pub/databases/Pfam/current_release/Pfam-A.seed.gz解压,取第一…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...