Sharing a mutable Vec across closures?

In an fltk based app, I have the following struct:

pub struct App {
	profile_vec: Vec<Profile>,
}

And code:

button_1.set_callback({
	let mut app = app.clone();
	move |_button| {
		let profile = app.create_profile_from_gui();
		app.profile_vec.push(profile);
	}
});

button_2.set_callback({
	let mut app = app.clone();
	move |_button| {
		if app.profile_vec.len() > 0 {
			do_something();
		}
	}
});

The intent is for all closures that clone App to have a shared vector (ie. Every closure has access to the same vec with the same data inside). I believe what I need is similar to the Arc<Mutex<Foo>> pattern for multithreaded cases but I cannot recall what it was.

You're going to want something like this:

use std::rc::Rc;
use std::cell::RefCell;

#[derive(Clone)]
pub struct SharedVec<T> {
    inner: Rc<RefCell<Vec<T>>>,
}

impl<T> SharedVec<T> {
    pub fn new() -> Self {
        Self {
            inner: Rc::new(RefCell::new(Vec::new())),
        }
    }

    pub fn push(&self, value: T) {
        self.inner.borrow_mut().push(value);
    }

    pub fn len(&self) -> usize {
        self.inner.borrow().len()
    }
}

Cloning the SharedVec gives a new shared handle to the same vector, and updates on one clone are visible in all other clones

Thanks! Seems to work as needed. Had to change it to use Arc<Mutex> since I forgot I was passing it to another thread elsewhere, do you know how to go about implementing get() in such case? That is, something like the following:

pub struct SharedVec<T> {
	inner: Arc<Mutex<Vec<T>>>,
}

impl<T> SharedVec<T> {
	pub fn get(&self, index: usize) -> Option<&T> {
		self.inner.lock().unwrap().get(index)
	}
}

It's impossible to return a reference that lives until after the lock guard goes out of scope. Consider cloning the value.

1 Like