多个closure引用同一个变量,并且可能需要mut borrow

目前在实现一个事件系统,事件采用保存closure的方式实现,这其中遇到一个比较棘手的问题就是如果其中一个closure用&mut方式捕捉了一个变量,那么其他closure就不可以再用任何方式捕捉这个变量(rust的borrow check系统),并且如果要&mut捕捉还需要把closure的类型写成FnMut,类似这种: add_event<F>(&mut self,f:F) where F:FnMut(...){}
目前折中的一个方法就是用Rc<RefCell<T>>的方式了,这个就是最终用户用起来很烦,大量的变量要用这种方式包裹。

use std::rc::Rc;
use std::cell::RefCell;

enum MyCall<'a>{
    Click(Box<Fn(i32)->i32 + 'a>),
    Down(Box<Fn(i32,i32)->i32 + 'a>),
    None,
}

struct Foo<'a>{
 calls:Vec<MyCall<'a>>,
}

impl<'a> Foo<'a>{
    fn new()->Foo<'a>{
        Foo{
 calls:Vec::new(),
        }
    }

 fn add_click<F>(&mut self,f: F)where F:Fn(i32)->i32+'a{
 self.calls.push(MyCall::Click(Box::new(f)));
    }

    fn do_call(&self){
 if let MyCall::Click(ref c) = self.calls[0] {
                println!("{}",(*c)(100));
        }

 if let MyCall::Click(ref c) = self.calls[1] {
                println!("{}",(*c)(100));
        }
    }
}

#[derive(Debug)]
struct A(i32);

#[derive(Debug)]
struct Bar{
 i:Rc<RefCell<A>>,
}

fn main(){
 let mut b = Bar{i:Rc::new(RefCell::new(A(200)))};
 let mut f = Foo::new();
    f.add_click(|i|{
        let bi = b.i.clone();
        let mut mbi = bi.borrow_mut();
        (*mbi).0 = 2000;
        (*mbi).0
        //b.0 = 100;
        //b.0
    });
    f.add_click(|i|{
        let bi = b.i.clone();
        let mut mbi = bi.borrow_mut();
        (*mbi).0 = 20000;
        (*mbi).0
    });
    f.do_call();
    println!("{:?}",b);
}

Play地址:http://is.gd/vdtWiG

输出:

2000
20000
Bar { i: RefCell { value: A(20000) } }

其实不用Rc也可以,大家可以看看这个,我目前对这个机制也不是太熟悉:
http://is.gd/78HF1Y

你可能感兴趣的:(事件,event,RC,Rust,refcell)