Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Borrowing reference in structure

Tags:

rust

I'm trying to put in one structure information about inotify events and hashmap with inotify watch id as key and name of the file as value.

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() {

        }
    }
}

During compilation I am receiving an error

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

I thought the best solution would be to separate somehow inotify variable in Notificator structure with watch_service, but I can't dereference self.check_for_events(); because I receive

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

I understand the core of the problem: I'm trying to borrow reference by check_for_events and then using it as parameter in events_execution which also requires self as parameter, but I have no idea how to resolve it.

like image 650
m0drzew Avatar asked Dec 14 '22 05:12

m0drzew


1 Answers

One thing you could do, although it's not very elegant, is to have your mutable method consume its mutable borrow and return an immutable one that you can then use:

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

I've made a small proof-of-concept on the playground (using vecs of u64 as the mutable state, but the principle is similar). It might be cleaner to refactor your code so that some external client can (mutably) borrow the Notifier, produce the events, release the borrow, and borrow it (immutably) to process them...

like image 61
val Avatar answered Dec 19 '22 12:12

val