Mutably use a value inside and outside of a closure

Viewed 71

Is there a way to mutably borrow (or move a reference to) some value into a closure and continue using it outside, in a cleaner way?

For example, I have this code:

let queue = Arc::new(RefCell::new(Vec::new()));
let cqueue = Arc::clone(&queue);

EntityEventQueue::register_receiver(&entity_equeue, "position-callback",
    Box::new( move |e| {
        cqueue.borrow_mut().push(e.clone());
    }));

// mutate queue

It works, but I heard that RefCell is bad practice outside some specific uses. Is there a way that I can use queue both inside and outside of the closure?

And if there is not, do you know a better way of implementing this? The one requirement is that the queue must be outside of the EntityEventQueue structure

(I created the register_receiver method, so it can be altered. Its signature is pub fn register_receiver(this: &Arc<RefCell<Self>>, name: &str, callback: Box<dyn FnMut(...) + 'a>)

1 Answers

You should use some synchronization mechanism instead of RefCell. For example a Mutex or a RwLock. Depending on your writing needs. Quick tip is:

  • One writer (at a time) and several readers -> RwLock
  • Many writers many readers -> Mutex

Those are std but you have some other synchronization libraries and mechanisms available.

Related