一.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.唤醒所有等待线程
接下来运行看一下结果: