rust学习(模拟Future)

一.future结构体

rust 复制代码
//声明
trait DefaultValue {//1
    fn getDefault()->Self;
}
struct MFuture<T> where T:DefaultValue + Copy{
    mutex:Mutex<(bool,T)>,//2
    cond:Condvar//3
}

struct MTask<T> where T:DefaultValue + Copy{
    future:Arc<MFuture<T>>,//4
    func:Box<dyn Fn()-> T + 'static + Send>,//5
}
//实现
impl DefaultValue for i32 {//6
    fn getDefault()->Self {
        0
    }
}

1.DefaultValue主要是为了初始化future的时候默认值需要赋值。没有办法,强行加了一个这个接口。

2.MFuture::mutex主要存储了一个元,包含了(是否完成,结果)这2项目

3.MFuture::cond主要是用来通知wait数据的线程。

4.MTask::future:存储了future的信息,用了智能指针,主要是等待线程需要持有一份,处理线程也需要持有一份,2个线程是通过future里面的cond来唤醒

5.MTask::func:存储了lambda函数

6.为I32实现了默认值的接口,方便后面初始化的时候获取默认值。

二.future实现

rust 复制代码
impl <T>MFuture<T> where T:DefaultValue + Copy{
    fn get(&self)-> T {
        loop {
            let mut complete = self.mutex.lock().unwrap();
            if complete.0.eq(&true) {
               return complete.1;
            } else {
                self.cond.wait(complete);
            }
        }
    }
}

原理比较简单,从future中获取数据元,如果元组第一个为true,则表明计算完成,直接返回数据,否则就调用condvar来等待。

三.模拟场景

线程1->list放入各种lambda函数

线程2->从list取出lambda函数,计算后将结果存放到future

线程1:

rust 复制代码
let mut list: Arc<Mutex<Vec<MTask<i32>>>> = Arc::new(Mutex::new(Vec::<MTask<i32>>::new()));//1
    
    let mut closure1 = list.clone();
    thread::spawn(move || {
        let mut count = 0;
        loop {
            thread::sleep(Duration::from_secs(1));

            let ll = || {
                println!("fn start");
                thread::sleep(Duration::from_secs(1));
                println!("fn finish start");
                123
            };//2

            let future = Arc::new(MFuture {
                mutex:Mutex::new((false,i32::getDefault())),
                cond:Condvar::new()
            }); //3

            let task = MTask {
                future:future.clone(),
                func:Box::new(ll)
            };//4

            {
                let mut l = closure1.lock().unwrap();
                l.push(task);
            } //5

            let f1 = future.clone();
            println!("v is {}",f1.get());//6
        }
    });

1.创建一个队列用来存放所有的task,类似一个生产者/消费者模型。

2.创建一个lambda函数,这里简单写了一个直接返回i32的函数,实际场景可能会是比较负责的函数。

3.生成一个future,这里i32::getDefault()获取默认数据,模板玩的不溜,这里直接写死了。照理应该不需要指定i32.

4.将回调函数保存下来,注意,这里是用Box来保存的。

5.将这个task推到队列里面

6.调用get函数 ,如果没有计算完,等待。哈哈。

线程2:

rust 复制代码
let mut closure2 = list.clone();
    thread::spawn(move || {
        loop {
            thread::sleep(Duration::from_millis(500));
            let mut v = closure2.lock().unwrap();
            if v.len() == 0 {
                continue;
            }

            let mut vv = v.pop().unwrap();
            let ret = (vv.func)();//1
            let mut comp = vv.future.mutex.lock().unwrap();
            comp.0 = true;//2
            comp.1 = ret;//2
            vv.future.cond.notify_all();//3
        }
    }).join();

1.调用线程1中保存的lambda函数,执行获取结果

2.更新future中用来保存运算结果的数据元。comp.0表示是否计算完成,comp.1存放运算结果

3.唤醒所有等待线程

接下来运行看一下结果:

相关推荐
chenbingjie_c7 小时前
C++ 进阶核心知识点总结:模板、内存分区、new/delete、内存池
开发语言·c++
Escalating_xu8 小时前
【C 语言】深入理解指针(1·下):指针运算、野指针、assert 与传址实战
java·c语言·开发语言
实心儿儿8 小时前
Qt — Qt 事件
开发语言·qt
差不多的周周8 小时前
《骨架上下文:基于零镜头骨架的动作识别的骨架侧上下文提示学习》论文核心部分详解
学习
周杰偷奶茶8 小时前
【Java】数据类型与变量
java·开发语言
code斗9 小时前
Java数据结构:堆详解
java·开发语言·数据结构
重生之小比特9 小时前
【C++进阶】map和set
java·开发语言·c++
lie..9 小时前
30天从零开始学AI应用开发(Day 12):像产品一样稳:流式输出、报错重试、花钱控制
开发语言·人工智能·php
傻啦嘿哟9 小时前
Python的默认参数把我坑惨了,原来写[]和写None的区别这么大
开发语言·python·机器学习
Century_Dragon9 小时前
从挂图到VR:汽修专业的一堂新能源原理课可以怎么上~
学习