在结构中借用引用

4

我正在尝试将关于inotify事件和哈希映射表的结构信息放入其中,其中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() {

        }
    }
}

在编译过程中,我遇到了一个错误。

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);

我认为最好的解决方案是以某种方式将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();

我理解问题的核心:我试图通过 check_for_events 借用引用并将其作为参数传递给需要 self 作为参数的 events_execution,但是我不知道如何解决它。

你在事件执行中使用 self 吗?如果不是,那么不将其作为参数可能会解决你的问题。 - Noctua
@Noctua,我忘记在帖子中写了,但是是的,我在事件执行中使用self。 - user2544133
2个回答

6

您可以做一件事情,虽然不是很优美,那就是让您的可变方法消耗它的可变借用,并返回一个不可变的借用,您随后可以使用它:

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)
}

我在playground上制作了一个小的概念验证,使用u64向量作为可变状态(但原理类似)。重构您的代码可能更加清晰,以便某些外部客户端可以(可变地)借用Notifier,生成事件,释放借用,并(不可变地)借用它来处理这些事件...


好的,我试图重写我的代码,但现在check_for_events函数的第二行出现了“ 'self' does not live long enough”的错误。 - user2544133
我认为我的代码可能在返回&self时不正确:但是返回声明为&Selfself似乎可以正常工作:playground link - val
fn check_for_events(&mut self) -> (&Self, &[inotify::wrapper::Event]) { let events = self.inotify.available_events().unwrap(); (self, events) }在第二行中,'self.inotify' 作为可变借用被占用,因此无法将 '*self' 作为不可变借用。在第一行中,'self.inotify' 的先前借用出现在此处。 - user2544133

4
这是借用检查器的已知问题(更多讨论内容)。如果你有一个将&mut T传递给对象并返回&T的函数,那么在&T超出作用域之前,就无法再次访问该对象。由于inotify的实现方式,你无法绕过它。
但是你可以要求inotify作者创建一个不获取新数据的get_available_notifications方法。这样,你可以调用available_notifications一次并放弃返回值。然后调用get_available_notifications(它只需要&INotify,而不是&mut INotify)并从那里开始工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接