前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【大家的项目】可 Deferred 就绪的 Future 实现类

【大家的项目】可 Deferred 就绪的 Future 实现类

作者头像
MikeLoveRust
发布于 2023-10-30 12:01:58
发布于 2023-10-30 12:01:58
28200
代码可运行
举报
运行总次数:0
代码可运行

deferred-future

模仿jQuery.Deferred(),允许

  • 【地点】从Future实现类实例外部
  • 【时间】异步地

改变当前Future对象的Polling状态从Poll::PendingPoll::Ready<T>。这个痛点是futures crate都没有照顾到的。

功能

deferred-future crate分别针对

  • 单线程/WASM
  • 多线程

提供了两套代码实现和两个自定义cargo feature

cargo feature

FusedFuture实现类

运行上下文

local

LocalDeferredFuture<T>

单线程/WASM

thread

ThreadDeferredFuture<T>

多线程

默认情况下,localthread都处于开启状态。为了追求极致的编译时间(短)与输出二进制文件体积(小),屏蔽掉未被使用的模块非常有帮助。比如,在WASM工程内,启用【条件编译】和(编译时)“裁剪”依赖包是最明智的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 因为 WASM 不支持【操作系统线程】,所以仅只导入单线程代码实现
deferred-future = {version = "0.1.0", features = ["local"]}

另外,因为deferred-future crate选择实现trait futures::future::FusedFuture,而不仅只是来自【标准库】的std::future::Future,所以其对更多“边界情况”提供了良好的容错支持。比如,

  • 重复地Polling一个已经Poll::Ready(T)Future实例不会导致U.B.

安装

不开启【条件编译】

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cargo add deferred-future

面向WASM,推荐仅开启local

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cargo add deferred-future --features=local

用法

使用套路概括起来包括:

  1. 构造一个***DeferredFuture<T>实例
    1. 在多线程上下文中,泛型类型参数T必须是Send + Sync的。
    2. 在单线程上下文中,前缀***Local
    3. 在多线程上下文中,前端***Thread
    4. 泛型类型参数T对应于Future::Output关联类型 —— 代表了Future就绪后输出值的数据类型
  2. ***DeferredFuture<T>实例抽取出defer属性值
    1. 被用来Wake up处于Pending状态***DeferredFuture<T>实例的complete(T)成员方法就隶属于此defer对象。
    2. 在单线程上下文中,deferRc<RefCell<T>>的引用计数·智能指针
    3. 在多线程上下文中,deferArc<Mutex<T>>的原子加锁引用计数·智能指针
  3. defer对象克隆后甩到(另)一个异步任务Task块中去。
    1. 在异步块内,调用defercomplete(T)成员方法。
    2. 在单线程上下文中,defer对象需被可修改借入defer.borrow_mut()
    3. 在多线程上下文中,需要先成功地获取线程同步锁defer.lock().unwrap()
  4. 在当前执行上下文,阻塞等待***DeferredFuture<T>实例就绪和返回结果。
    1. 就单线程而言,当前执行上下文即是“主线程”,和同步阻塞主线程。
    2. 就多线程而言,当前执行上下文就是“父异步块”,和异步阻塞上一级异步块。

下面仔细看代码例程。请特别留意注释说明。

单线程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use ::deferred_future::LocalDeferredFuture;
use ::futures::{future, executor::LocalPool, task::LocalSpawnExt};
use ::futures_time::{prelude::*, time::Duration};
use ::std::time::Instant;
// (1) 构造·形似 jQuery.Deferred() 的 trait FusedFuture 实现例类实例。
//     - 注意:泛型类型参数 —— `Future::Output`输出值类型是字符串。
let deferred_future = LocalDeferredFuture::default();
// (2) 取出它的 defer 实例。
let defer = deferred_future.defer();
// (3) 发起一个异步任务。在 2 秒钟后,填入`Future::Output`输出值。
let mut executor = LocalPool::new();
executor.spawner().spawn_local(async move {
    future::ready(()).delay(Duration::from_secs(2_u64)).await;
    // (3.1) 在异步块内,调用`defer`的`complete(T)`成员方法。
    defer.borrow_mut().complete("2秒钟后才被延迟填入的消息".to_string());
}).unwrap();
// (4) 同步阻塞主线程等待 #3 的异步任务执行结果,和抽取出`Future::Output`输出值。
let start = Instant::now();
let message = executor.run_until(deferred_future); // (4.1) 会造成主线程的同步阻塞
let end = Instant::now();
let elapse = end.duration_since(start).as_secs();
println!("为了收到消息<{}>,主协程先后等待了 {} 秒", message, elapse);

从命令行,执行命令cargo.exe run --example local-usage可直接运行此例程。

多线程

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use ::deferred_future::ThreadDeferredFuture;
use ::futures::{future, executor::{block_on, ThreadPool}, task::SpawnExt};
use ::futures_time::{prelude::*, time::Duration};
use ::std::{error::Error, sync::PoisonError, time::Instant};
block_on(async move {
    // (1) 构造·形似 jQuery.Deferred() 的 trait FusedFuture 实现类实例。
    //     - 注意:泛型类型参数 —— `Future::Output`输出值类型是字符串。
    //     - String 是 Send + Sync 的数据类型,和支持跨线程传递的。
    let deferred_future = ThreadDeferredFuture::default();
    // (2) 取出它的 defer 实例。
    let defer = deferred_future.defer();
    // (3) 发起一个异步任务。在 1 秒钟后,填入`Future::Output`输出值。
    ThreadPool::new()?.spawn(async move {
        future::ready(()).delay(Duration::from_secs(1_u64)).await;
        // (3.1) 在异步块内,调用`defer`的`complete(T)`成员方法。
        let mut defer = defer.lock().unwrap_or_else(PoisonError::into_inner);
        defer.complete("1秒钟后才被延迟填入的消息".to_string());
    })?;
    // (4) 异步阻塞当前 Task 等待 #3 的异步任务执行结果,和抽取出`Future::Output`输出值。
    let start = Instant::now();
    let message = deferred_future.await; // (4.1) 会造成上一级异步块的异步阻塞
    let end = Instant::now();
    let elapse = end.duration_since(start).as_secs();
    println!("为了收到消息<{}>,主协程先后等待了 {} 秒", message, elapse);
    Ok(())
})?;

从命令行,执行命令cargo.exe run --example thread-usage可直接运行此例程。

WASM

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
use ::deferred_future::LocalDeferredFuture;
use ::wasm_gloo_dom_events::{EventStream, Options};
// (1) 构造·形似 jQuery.Deferred() 的 trait FusedFuture 实例类实例。
//     - 注意:泛型类型参数 —— `Future::Output`输出值类型是 u32。
let deferred_future = LocalDeferredFuture::default();
// (2) 取出它的 defer 实例。
let defer = deferred_future.defer();
// (3) 给按钮 DOM 元素添加一个鼠标单击事件。仅当按钮被单击时,才填入`Future::Output`输出值。
let _ = EventStream::on(&button, "click", Options::enable_prevent_default(true), move |event| {
    // (3.1) 在 DOM 事件处理函数内,调用`defer`的`complete(T)`成员方法。
    defer.borrow_mut().complete(12);
    future::ready(Ok(()))
});
wasm_bindgen_futures::spawn_local(async move {
    // (4) 异步阻塞当前 Task 等待 #3 的按钮点击事件的发生,和抽取出`Future::Output`输出值。
    let result = deferred_future.await;
    console::info!("DeferredFuture异步结果", result);
});
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-10-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust语言学习交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
如何绘制符合规范的流程图表_流程图画法规范
流程图可以简单地描述一个过程,是对过程、算法、流程的一种图像表示,在技术设计、交流及商业简报等领域有广泛的应用。流程图可分为:数据流程图和作业流程图。
全栈程序员站长
2022/09/20
4.1K0
如何绘制符合规范的流程图表_流程图画法规范
关于写作那些事之快速上手Mermaid流程图
本文主要介绍了如何快速上手 Mermaid 流程图,不用贴图上传也不用拖拉点拽绘制,基于源码实时渲染流程图,操作简单易上手,广泛被集成于主流编辑器,包括 markdown 写作环境.
雪之梦技术驿站
2020/05/07
3.6K0
关于写作那些事之快速上手Mermaid流程图
Markdown的时序图、流程图、和甘特图+Hexo的相关配置
本贴在手机端因为mermaid插件的问题显示会超出屏幕,以后在想办法解决,目前建议使用电脑浏览
impressionyang
2020/08/27
2.5K0
使用 markdown 画流程图、时序图
在日常工作中,难免会画一些流程图、时序图。之前都是选择使用在线的画图网站,画完然后截图插入到文档。我个人用的比较多的主要是 腾讯文档 。
Mervyn
2021/12/08
2.8K0
使用 markdown 画流程图、时序图
手把手教你画流程图
1)用于和非研发部门交流: 决定人员都做什么工作?描述公司的核心业务。例如用户下单后,就涉及到物流部门进行发货,系统进行开发票等工作。
matinal
2020/11/27
2.2K0
手把手教你画流程图
java流程图平行四边形_编程技巧之流程图「建议收藏」
我们写的程序都是有逻辑顺序的,即是有流程的,流程图的作用则是对这种逻辑顺序的一种描述,是对解决问题的方法、思路或者算法的图形化的展示。
全栈程序员站长
2022/07/31
1.3K0
java流程图平行四边形_编程技巧之流程图「建议收藏」
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
如果您希望直接访问Vue3导入mermaid的代码,可以直接访问:三、Vue3中如何引入mermaid
watermelo37
2025/01/22
5840
高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
使用LaTeX的TikZ宏包绘制流程图
类似于css的思想,这个其实就是先定义一下样式然后调用,调用的时候也可以修改,大多数参数也能猜(确信
gyro永不抽风
2021/05/21
4.7K0
流程图之美:手把手教你设计一个流程图
流程图是一种图形化工具,主要用于表示完成一项任务的流程、工作流或具体方法。它通过箭头连接各种符号来展示流程步骤,并且通常从一个明确的起始点出发,按照一定的顺序和路径进行展开。今天小编就以葡萄城公司的纯前端表格控件——SpreadJS为例,为大家介绍如何设计一个流程图。
用户10920694
2024/02/02
2020
流程图之美:手把手教你设计一个流程图
UML 教程
UML 从来源中使用相当多的概念。我们将之定义于统一建模语言术语汇表。下面仅列代表性的概念。
静默虚空
2019/05/25
3.4K0
流程图 & 时序图绘制小 tips
在日常工作中,无论是产品经理写 PRD 或是开发、测试同学写技术方案、整理业务文档等场景都会用到诸如流程图、时序图、用例图、泳道图等形式的图来辅助阅读者理解。相信平时工作中有画图需要的读者都有这样的感受:有些图制作过程非常简单但逻辑清晰又不失美观,而有些图费时费力制作繁琐,但效果却不是特别惊艳,这其中的底层逻辑尤为关键,毕竟作图也是一门艺术。本文将会以直播商品讲解业务场景出发,给大家分享一些画图小知识。
得物技术
2023/08/29
2.9K0
流程图 & 时序图绘制小 tips
UML–活动图详解
活动图是状态机的一个特殊例子,它强调计算过程中的顺序和并发步骤。活动图所有或多数状态都是活动状态或动作状态,所有或大部分的转换都由原状态中完成的活动触发。
全栈程序员站长
2022/08/12
6.2K0
UML–活动图详解
软件工程期末考试复习(五) 设计问题过程设计的工具程序复杂程度的定量度量
1、程序流程图又称为程序框图,它是使用最广泛的描述过程设计的方法。程序流程图中使用的符号(a) 选择(分支); (b) 注释; (c) 预先定义的处理; (d) 多分支; (e) 开始或停止; (f) 准备; (g) 循环上界限; (h) 循环下界限; (i) 虚线; (j) 省略符; (k) 并行方式; (l) 处理; (m) 输入输出; (n) 连接; (o) 换页连接; (p) 控制流
用户2417870
2019/09/18
1.1K0
软件工程期末考试复习(五)

        设计问题过程设计的工具程序复杂程度的定量度量
java流程图平行四边形_流程图图形标准含义[通俗易懂]
作用:一般用作要执行的处理(process),在程序流程图中做执行框。在Axure中如果是画页面框架图,那么也可以指代一个页面。你可把页面和执行命令放在同一个流程中做说明,这个时候将两类不同的矩形做色彩区别,然后做说明就好了。
全栈程序员站长
2022/07/25
2.4K0
java流程图平行四边形_流程图图形标准含义[通俗易懂]
如何看懂常用原理图符号、如何阅读原理图
原理图是我们设计,构建和排除电路故障的地图。了解如何阅读和遵循原理图是任何电子工程师的重要技能。
不脱发的程序猿
2021/01/20
4.1K0
流程图设计入门指南 —— 以 Draw.io 为例
直接按保存, 会保存一个新的 xml 文件(当然, 这也间接实现了版本控制), 但是每次都要弹出窗口很麻烦 点击 File->Saveas... 选择 Browser , 浏览器便会实时保存记录,注意不要在无痕模式使用,否则误关闭浏览器也无法找回。
benny
2019/12/12
17.9K0
流程图设计入门指南 —— 以 Draw.io 为例
【愚公系列】软考高级-架构设计师 075-业务流程设计和分类
业务流程设计(Business Process Design, BPD)是指对组织中的各项活动和操作进行系统化的分析、规划和优化,以提高效率、降低成本、提升质量和增强客户满意度的过程。业务流程设计的核心目的是通过重新思考和重新设计企业内部的工作流程和结构,使其更加高效、灵活和适应变化的市场需求。
愚公搬代码
2024/07/29
2190
业务流程图绘制分享
流程:是指特定主体为了满足特定需求而进行的有特定逻辑关系的一系列操作过程,流程是自然而然就存在的。但是它可以不规范,可以不固定,可以充满问题。所以就会造成看似没有流程。
公爵
2022/09/28
9080
业务流程图绘制分享
流程图的画法说明和部分详解
最近项目开发,公司部分人走掉了。3、4月份求职高峰期。找来的新人,由我带领,讲解业务相当麻烦,而且还需要每个人都讲解一遍。因此我就结合现有的功能画了流程图和序列图。我这里就先讲解流程图了。流程图:使用图形表示算法的思路是一种极好的方法,因为千言万语不如一张图。流程图在汇编语言和早期的BASIC语言环境中得到应用。相关的还有一种PAD图,对PASCAL或C语言都极适用。工具使用的visio 2007,由于太大了,这里就不做上传了。
业余草
2019/01/21
1.9K0
流程图的画法说明和部分详解
3 C语言 流程控制 循环 跳转
前面的章节一直在介绍C语言的基本语法知识,然而仅仅依靠这些语法知识还不能编写出完整的程序。在程序中,通常需要加入业务逻辑,并对程序的流程进行控制。本章将重点讲解C语言中最基本的三种流程控制语句。
py3study
2020/01/08
2.1K0
3 C语言 流程控制 循环 跳转
推荐阅读
相关推荐
如何绘制符合规范的流程图表_流程图画法规范
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档