Rust语言通过定义了Future Trait , 奠定了异步语法的基石,而Rust的异步代码时惰性的,必须有一个运行时来驱动,Rust本身还没提供这样的实现,社区中有不少开源方案,比如tokio等。

Tokio的运行时是一个事件循环,利用了不同平台的异步非阻塞特性,比如kqueue,epoll等。

我一直想要弄清楚runtime是怎么调度Future,而Future完成时又是怎么通知runtime,extreme 实现了一个最小运行时,可以让一窥究竟。

use std::sync::{Arc, Condvar, Mutex};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker}; #[derive(Default)]
struct Park(Mutex<bool>, Condvar); fn unpark(park: &Park) {
*park.0.lock().unwrap() = true;
park.1.notify_one();
} static VTABLE: RawWakerVTable = RawWakerVTable::new(
|clone_me| unsafe {
let arc = Arc::from_raw(clone_me as *const Park);
std::mem::forget(arc.clone());
RawWaker::new(Arc::into_raw(arc) as *const (), &VTABLE)
},
|wake_me| unsafe { unpark(&Arc::from_raw(wake_me as *const Park)) },
|wake_by_ref_me| unsafe { unpark(&*(wake_by_ref_me as *const Park)) },
|drop_me| unsafe { drop(Arc::from_raw(drop_me as *const Park)) },
); /// Run a `Future`.
pub fn run<F: std::future::Future>(mut f: F) -> F::Output {
let mut f = unsafe { std::pin::Pin::new_unchecked(&mut f) };
let park = Arc::new(Park::default());
let sender = Arc::into_raw(park.clone());
let raw_waker = RawWaker::new(sender as *const _, &VTABLE);
let waker = unsafe { Waker::from_raw(raw_waker) };
let mut cx = Context::from_waker(&waker); loop {
match f.as_mut().poll(&mut cx) {
Poll::Pending => {
let mut runnable = park.0.lock().unwrap();
while !*runnable {
runnable = park.1.wait(runnable).unwrap();
}
*runnable = false;
}
Poll::Ready(val) => return val,
}
}
}

这个简短的例子表达了实现一个运行时的最低需求

  • 实现RawWakerVTable
  • 如何通过Waker唤醒runtime继续调度,这里用了信号量

本质上运行时可以抽象成一个不断运行的循环体,在循环体内不断调用Future的poll方法。

(当Future返回Poll::Pending时,此处简化为使用信号量的等待操作)

这个例子也说明了Future的调用能返回时,需要调用存储在ctx里面的Waker::waker()方法,唤醒运行时继续执行阻塞的异步任务

Rust异步运行时最小实现 - extreme 分享的更多相关文章

  1. Rust异步之Future

    对异步的学习,我们先从Future开始,学习异步的实现原理.等理解了异步是怎么实现的后,再学习Rust异步编程涉及的2个库(futures.tokio)的时候就容易理解多了. Future rust中 ...

  2. Rust语言——无虚拟机、无垃圾收集器、无运行时、无空指针/野指针/内存越界/缓冲区溢出/段错误、无数据竞争

    2006年,编程语言工程师Graydon Hoare利用业余时间启动了Rust语言项目.该项目充分借鉴了C/C++/Java/Python等语言的经验,试图在保持良好性能的同时,克服以往编程语言所存在 ...

  3. [翻译]Go与C#对比 第三篇:编译、运行时、类型系统、模块和其它的一切

    Go vs C#, Part 3: Compiler, Runtime, Type System, Modules, and Everything Else | by Alex Yakunin | S ...

  4. ASP.NET运行时详解 集成模式和经典模式

    遗留问题 在<ASP.NET运行时详解 生命周期入口分析>中遗留两个问题,包括Application的InitInternal方法执行细节.IIS6和II7经典模式请求管道管理类Appli ...

  5. JavaScript是如何工作的:引擎,运行时和调用堆栈的概述!

    摘要: 理解JS执行原理. 原文:JavaScript是如何工作的:引擎,运行时和调用堆栈的概述! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 本文是旨在深入研究JavaScrip ...

  6. Tokio,Rust异步编程实践之路

    缘起 在许多编程语言里,我们都非常乐于去研究在这个语言中所使用的异步网络编程的框架,比如说Python的 Gevent.asyncio,Nginx 和 OpenResty,Go 等,今年年初我开始接触 ...

  7. 第28 章 : 理解容器运行时接口 CRI

    理解容器运行时接口 CRI CRI 是 Kubernetes 体系中跟容器打交道的一个非常重要的部分.本文将主要分享以下三方面的内容: CRI 介绍 CRI 实现 相关工具 CRI 介绍 在 CRI ...

  8. Dapr中国社区活动之 分布式运行时开发者日 (2022.09.03)

    自2019年10月首次发布以来,Dapr(Distributed Application Runtime,分布式应用运行时)因其"更稳定"."更可靠".&quo ...

  9. 1. Activiti 运行时表信息总结

    Activiti的后台是有数据库的支持,所有的表都以ACT_开头. 第二部分是表示表的用途的两个字母标识. 用途也和服务的API对应. ACT_RE_*: 'RE'表示repository. 这个前缀 ...

  10. linux下实现在程序运行时的函数替换(热补丁)

    声明:以下的代码成果,是参考了网上的injso技术,在本文的最后会给出地址,同时非常感谢injso技术原作者的分享. 但是injso文章中的代码存在一些问题,所以后面出现的代码是经过作者修改和检测的. ...

随机推荐

  1. 一、Linux常用命令(ubuntu/debian)

    1.rename(批量修改文件名) rename 's/屏幕录制 2024-09-06 123248_/aa_/' 屏幕录制\ 2024-09-06\ 123248_*.png 这条命令的含义是: s ...

  2. Win10更新为Win11失败,可尝试用Win11 安装助手升级。

    Win10更新为Win11总是失败的,可以试一下Windows 11 安装助手. ​而且,系统自动更新后只能是Win11的23H2版本,后面还需要继续更新.而安装助手直接升级到24H2的最新版本. W ...

  3. Django+DRF 实战:从异常捕获到自定义错误信息

    一.DRF 异常 介绍 APIException 类是 DRF 异常的基类.通过继承APIException,DRF 提供了多种内置异常类. ParseError:当请求解析失败时抛出. Authen ...

  4. 前端开发系列026-基础篇之Canvas绘图(曲线)

    本文将介绍Canvas中的弧度.曲线.圆弧以及文字的绘制方法以及径向渐变等内容,并提供饼状图等综合案例. 一.Canvas中的弧度.曲线和圆弧 专业术语 夹角 从一个点发射(延伸)出两条线段,两条线相 ...

  5. apt 相关操作

    apt-cache search XXX 寻找相关的包 apt-cache showpkg XXX 显示相关包的信息 sudo apt-get --purge remove *** 移除相关的包 dp ...

  6. matlab 求解常微分方程

    简介 高数中关于求解常微分方程,我一直记得是公式 code clc, clear syms y(x) % 定义符号常量 dsolve(x^2 + y + (x -2 * y) * diff(y) == ...

  7. USB3.0 PHY方案(FT601Q)在 FPGA上的速率验证

    一.背景 高通量在体神经信号采集系统,随着通道数增加.增加实时刺激需求等,采用以太网传输面临带宽极限,亟需一种更快的传输介质. 目前以太网的带宽极限:实测800Mbit/s左右,[移植并使用Iperf ...

  8. ETL快速同步 用友u8数据方式

    在企业信息化进程中,用友U8作为一款广泛应用的ERP系统,承载着企业核心业务数据.为了实现这些数据的有效利用与深度分析,往往需要通过ETL(Extract, Transform, Load)工具进行快 ...

  9. SciTech-AV-Audio-Coding-Sampling-PCM:Multiplex(FD频分/TD时分多工)+DPCM(Delta增量)+ADPCM(Adaptive Delta自适应增量) + Oversampling超采样

    pdf: https://web.stanford.edu/class/ee179/lectures/notes13.pdf EE 179: Communication Systems Textboo ...

  10. Math-AdvancedAlgebra-行列式

    A11 A12 A21 A22