rust学习(模拟Future)

一.future结构体

//声明
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实现

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:

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:

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.唤醒所有等待线程

接下来运行看一下结果:

相关推荐

  1. Future设计模式

    2024-03-10 10:26:03       31 阅读
  2. rust高级 异步编程 一 future

    2024-03-10 10:26:03       35 阅读
  3. Rust个人学习之包&模块

    2024-03-10 10:26:03       19 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-10 10:26:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-10 10:26:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-10 10:26:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-10 10:26:03       20 阅读

热门阅读

  1. nextjs上的DDD架构

    2024-03-10 10:26:03       21 阅读
  2. 分布式BASE理论

    2024-03-10 10:26:03       25 阅读
  3. AI辅助研发正在成为造福人类的新生科技力量

    2024-03-10 10:26:03       22 阅读
  4. 用cin和cout实现数据的输入输出——例题

    2024-03-10 10:26:03       20 阅读
  5. 我是如何写作的?

    2024-03-10 10:26:03       22 阅读
  6. vscode remote ssh 连接 ubuntu/linux报错解决方法

    2024-03-10 10:26:03       21 阅读
  7. 5.56 BCC工具之funcslower.py解读

    2024-03-10 10:26:03       23 阅读