Many libraries enable you to define a type that implements a specific trait to serve as a callback handler. This necessitates combining all the data required to handle an event into a single data type, which complicates borrowing.
For example, with
在这种排列中,即使直观上可以看到
一种可能的方法是将
这个方法可行但感觉有些笨拙。它还会引入每个方法调用中在self中移动值的开销。
有什么更好的方法吗?
For example, with
mio
, you can implement Handler
and provide your struct when you run the EventLoop
. Consider this example with simplified data types:struct A {
pub b: Option<B>
};
struct B;
struct MyHandlerType {
pub map: BTreeMap<Token, A>,
pub pool: Pool<B>
}
您的处理程序有一个从Token
到类型为A
的项目的映射。每个类型为A
的项目可能已经具有或没有关联的类型B
的值。在处理程序中,您希望查找给定Token
的A
值,并且如果它还没有B
值,则从处理程序的Pool<B>
中获取一个。
impl Handler for MyHandlerType {
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
}
}
在这种排列中,即使直观上可以看到
self.map
和self.pool
是不同的实体,但借用检查器会抱怨当我们去访问self.pool
时self
已经被借用(通过self.map
)。一种可能的方法是将
MyHandlerType
中的每个字段包装在Option<>
中。然后,在方法调用开始时,从self
中take()
这些值,并在调用结束时恢复它们。struct MyHandlerType {
// Wrap these fields in `Option`
pub map: Option<BTreeMap<Token, A>>,
pub pool: Option<Pool<B>>
}
// ...
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
// Move these values out of `self`
let map = self.map.take().unwrap();
let pool = self.pool.take().unwrap();
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
// Restore these values to `self`
self.map = Some(map);
self.pool = Some(pool);
}
这个方法可行但感觉有些笨拙。它还会引入每个方法调用中在self中移动值的开销。
有什么更好的方法吗?