Borrowing vector in closure

In my application, I'm intending to borrow a vector inside a closure, which adds a file to the vector when called. However, in my implementation I get the following error: closure may outlive the current function, but it borrows files, which is owned by the current function.

I understand why the error occurs, but I'm unsure, after having searched for possible solutions, how to best implement what I want.

Below is a simplified version of my main function. In my real implementation, I'm accessing individual files from the files vector in the loop and processing them.

fn main() {
    let mut files: Vec<String> = Vec::new();
    let event_fn = |res: NotifyResult<notify::Event>| {
        match res {
            Ok(event) => {
                // println!("event: {:?}", event);
                if event.kind.is_access() && event.kind == EventKind::Access(AccessKind::Close(AccessMode::Write)) {
                    // loop over each path in event.paths
                    for path in event.paths {
                        // println!("path: {:?}", path);
                        files.push(path.to_str().unwrap().to_string());
                    }
                }
            },
            Err(e) => println!("watch error: {:?}", e),
        }
    };

    let mut watcher = notify::recommended_watcher(event_fn).unwrap();
    watcher.watch("/tmp", RecursiveMode::NonRecursive).unwrap();
    loop {
        println!("files: {:?}", files);
        std::thread::sleep(std::time::Duration::from_secs(1));
    }
}

Your closure (EventHandler implementer) has to be Send + 'static, so you'll need some sort of shared ownership here -- like an Arc<Mutex<Vec<_>>>. And perhaps a Condvar for this use case.

3 Likes

On second thought, this is a good use-case for some sort of channel. Have your closure own the sender, and send new paths when you get an event. Then you can block on receiving instead of sleeping or a Condvar.

4 Likes