rust学习(tokio future分析)

自己编写一个impl future来看一下Tokio的是如何实现的。

第一步:

代码:

struct TExecuteTask {count:u32
}impl Future for TExecuteTask {type Output = ();fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {println!("future require");if self.count == 2 {return Ready(());}unsafe {self.get_unchecked_mut().count += 1;}Pending}
}pub fn test1() {let v = TExecuteTask{count:0};let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();println!("test trace1");rt.block_on(v);println!("test trace2");
}

运行结果:

貌似调用block_on之后会回调一次future的poll,如果这个时候还没有计算出结果,那就直接卡死了,所以需要找个地方能唤醒。

第二步:

原来代码上添加上wake

impl Future for TExecuteTask {type Output = ();fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {println!("future require");let mut v = self.core.lock().unwrap();v.waker = Some(cx.waker().clone());Pending}
}pub fn test1() {let waker: Arc<Mutex<TExecuteTaskCore>> = Arc::new(Mutex::new(TExecuteTaskCore {waker:None}));let task: TExecuteTask = TExecuteTask {core:waker.clone()};let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();let closure1 = waker.clone();thread::spawn(move|| {thread::sleep(Duration::from_secs(1));let mut core: std::sync::MutexGuard<'_, TExecuteTaskCore> = closure1.lock().unwrap();if let Some(waker) = core.waker.take() {println!("detect future is ready, wakeup the future task to executor.");waker.wake()    // wakeup the future task to executor.}});println!("test trace1");rt.block_on(task);println!("test trace2");
}

关键是在poll返回pending的时候,获取waker。然后等计算完成后再wake一下哈哈。

然后结果呢:

还是卡住了。。。这个是为啥呢?原来是我poll的代码有问题,无论如何处理都是返回pending..

所以从目前的试验来看有如下结论:

1.当调用block_on的时候,会直接调用一次future的poll确认是否运算结束。

2.当调用waker.wake的时候貌似还会调用一次poll确认是否运算结束。

所以我们现在要加一个标志位来表示运算结束,这样block_on应该就能正常走下去了吧。

第三步:

impl Future for TExecuteTask {type Output = ();fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {println!("future require");let mut v = self.core.lock().unwrap();if v.complete == true {return Ready(())}v.waker = Some(cx.waker().clone());Pending}
}pub fn test1() {let waker: Arc<Mutex<TExecuteTaskCore>> = Arc::new(Mutex::new(TExecuteTaskCore {waker:None,complete:false}));let task: TExecuteTask = TExecuteTask {core:waker.clone()};let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap();let closure1 = waker.clone();thread::spawn(move|| {thread::sleep(Duration::from_secs(1));let mut core: std::sync::MutexGuard<'_, TExecuteTaskCore> = closure1.lock().unwrap();if let Some(waker) = core.waker.take() {println!("detect future is ready, wakeup the future task to executor.");core.complete = true;waker.wake()    // wakeup the future task to executor.}});println!("test trace1");rt.block_on(task);println!("test trace2");
}

添加了一个complete标志运算是否结束。

运算完成后,complete赋值为true,再尝试wake一下等待线程(协程?)

poll中也添加了complete判断,如果为true的话,直接返回Ready,然后我们看一下运行结果:

运行结束~~。哈哈。

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

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

相关文章

Pygame教程03:文本显示+字体加载+transform方法

------------★Pygame系列教程★------------ Pygame教程01&#xff1a;初识pygame游戏模块 Pygame教程02&#xff1a;图片的加载缩放旋转显示操作 Pygame教程03&#xff1a;文本显示字体加载transform方法 Pygame教程04&#xff1a;draw方法绘制矩形、多边形、圆、椭圆、弧…

Java8,函数式编程应用:

持续更新中&#xff1a; 函数式(Functional)接口 什么是函数式(Functional)接口 只包含一个抽象方法的接口&#xff0c;称为函数式接口。 你可以通过 Lambda 表达式来创建该接口的对象。&#xff08;若 Lambda 表达式 抛出一个受检异常(即&#xff1a;非运行时异常)&#xff0c…

Crossbar阵列的电路结构及其基本原理

忆阻器Crossbar阵列是一种先进的神经网络硬件实现技术&#xff0c;它利用忆阻器的物理特性来模拟神经网络中的突触连接&#xff0c;为人工智能和机器学习应用提供了一种高效、低能耗的计算平台。本文将深入探讨忆阻器Crossbar阵列的基本原理及其在Read&#xff08;读取&#xf…

运维随录实战(2)之k8s部署应用

一, 创建.gitlab-ci.yml文件 架构流程 文件内容 stages: #设置流水线模版- build # 编译- source2img- deploy # 发布variables: # 设置全局变量MAVEN_PATH: .m2MAVEM_IMAGE: maven:3.8.5-openjdk-17-slim # maven 打包使用的镜像MAVEN_CLI_OPTS: "-s $MAVEN_PATH/set…

稀碎从零算法笔记Day7-LeetCode:罗马数字转整数

题型&#xff1a;字符串转化、找规律 链接&#xff1a;13. 罗马数字转整数 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 …

【深圳五兴科技】Java后端面经

本文目录 写在前面试题总览1、java集合2、创建线程的方式3、对spring的理解4、Spring Boot 和传统 Spring 框架的一些区别5、springboot如何解决循环依赖6、对mybatis的理解7、缓存三兄弟8、接口响应慢的处理思路9、http的状态码 写在前面 关于这个专栏&#xff1a; 本专栏记录…

抖音视频下载软件|视频批量采集工具

便捷操作&#xff0c;高效采集 在快节奏的数字化时代&#xff0c;我们的视频下载软件提供了简单便捷的操作流程&#xff0c;让用户能够高效地采集所需视频内容。用户只需输入关键词并点击开始抓取&#xff0c;系统会自动搜索指定关键词下的抖音视频数据&#xff0c;并将待解析视…

C语言第三十五弹---文件操作(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 文件操作 1、为什么使用文件&#xff1f; 2、什么是文件&#xff1f; 2.1、程序文件 2.2、数据文件 2.3、文件名 3、二进制文件和文本文件 4、文件的打开和…

折线图 温度变化曲线图

代码详情介绍 导入必要的库&#xff1a; matplotlib.pyplot&#xff1a;用于绘图。 matplotlib.font_manager&#xff1a;用于设置中文字体。 datetime&#xff1a;用于处理日期和时间。 random&#xff1a;用于生成随机数。 numpy&#xff1a;用于生成arange函数的刻度。 设置…

Linux系统使用宝塔面板安装MySQL服务并实现公网远程访问本地数据库【内网穿透】

文章目录 前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 宝塔面板的简易操作性,使得运维难度降低,简化了Linux命令行进行繁琐的配置,下面简单几步,通过宝塔面板cp…

【C语言】Leetcode 876. 链表的中间节点

主页&#xff1a;17_Kevin-CSDN博客 专栏&#xff1a;《Leetcode》 题目 通过题目的要求可以判断出有两种示例要解决&#xff0c;一种是偶数节点的链表&#xff0c;一种是奇数节点的链表&#xff0c;应对这两种情况我们需要使程序对二者都可以兼容。 解决思路 struct ListNode…

微服务相关的核心概念及技术

RPC框架&#xff1a; 在微服务架构中&#xff0c;服务与服务之间要实现接口的调用我们肯定要通过相关的RPC(Remote Procedure Call)框架来实现。 常用的RPC框架有:Dubbo&#xff0c;Google的GRPC&#xff0c;Apache的Thrift&#xff0c;微博的Motan&#xff0c;京东的EasyRPC等…