我正在尝试将一个关于inotify事件和hashmap的结构信息与inotify watch id作为键和文件名作为值.
extern crate inotify;
use inotify::INotify;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;
struct Notificator {
inotify: INotify,
watch_service: Arc<Mutex<HashMap<inotify::wrapper::Watch, Arc<String>>>>,
}
impl Notificator {
pub fn new() -> Notificator {
Notificator {
inotify: INotify::init().unwrap(),
watch_service: Arc::new(Mutex::new(HashMap::new())),
}
}
pub fn resolving_events(&mut self) {
{
let mut events = self.check_for_events();
self.events_execution(events);
}
}
fn check_for_events(&mut self) -> &[inotify::wrapper::Event] {
self.inotify.available_events().unwrap()
}
fn events_execution(&self, events: &[inotify::wrapper::Event]) {
for event in events.iter() {
}
}
}
Run Code Online (Sandbox Code Playgroud)
在编译期间,我收到一个错误
src/main.rs:204:13: 204:17 error: cannot borrow `*self` as immutable because it is also borrowed as mutable [E0502]
src/main.rs:204 self.events_execution(events);
Run Code Online (Sandbox Code Playgroud)
我认为最好的解决方案是将Notificator结构中的inotify变量与watch_service分开,但我无法取消引用self.check_for_events();因为我收到了
src/main.rs:203:17: 203:27 error: the trait bound `[inotify::wrapper::Event]: std::marker::Sized` is not satisfied [E0277]
src/main.rs:203 let mut events = *self.check_for_events();
Run Code Online (Sandbox Code Playgroud)
我理解问题的核心:我正在尝试借用引用check_for_events然后将其用作参数,events_execution其中也需要self作为参数,但我不知道如何解决它.
你可以做的一件事,虽然它不是很优雅,但是让你的可变方法消耗它的可变借用并返回一个你可以使用的不可变方法:
pub fn resolving_events(&mut self) {
let (slf, events) = self.check_for_events();
slf.events_execution(events);
}
fn check_for_events(&mut self) -> (&Self, &[inotify::wrapper::Event]) {
let events = self.inotify.available_events().unwrap();
(&self, events)
}
Run Code Online (Sandbox Code Playgroud)
我在操场上做了一个小概念验证(使用vecs u64作为可变状态,但原理类似).重构代码可能更清晰,以便某些外部客户端可以(可以)借用Notifier,生成事件,释放借用,并借用它(不可变地)来处理它们......
这是借位检查器中的一个已知问题(有关内部的更多讨论)。您不能有一个函数将一个&mut T对象带到一个对象并返回a,&T而又不会失去再次访问该对象的能力,直到&T超出范围。由于inotify实施方式,您无法解决它。
但是您可以要求inotify作者创建一种get_available_notifications不获取新数据的方法。这样,您可以调用available_notifications一次并删除返回值。然后致电get_available_notifications(不需要&mut INotify,而只需&INotify)从那里开始工作。