Is there a nicer way to have two closures have mutable access to the same variable?

I'm trying to invoke multiple (different) callbacks during an operation

Here's my code:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=fac50eba5d427a850f8821e852e4bd3d

It uses refcell (runtime cost?), and requires an explicit borrow statement at the start of each closure.

Is there a better way to do this?

You can use Cell, which doesn't have the runtime cost:

use std::cell::Cell;

let var = Cell::new(0);
gets_closures(
    || {
        var.set(var.get() + 1);
    },
    || {
        var.set(var.get() + 2);
    },
);

Can you give an example of how you want to use this? In many cases, it is possible to reorganize the code to avert this problem.

In my actual code I want to push to a VecDeque (which is not Copy obviously)

In that case, with the information available so far, RefCell would probably be the best way without resorting to unsafe code, I suppose.

Perhaps crossbeam::queue::SegQueue?

2 Likes

If you can control how the callbacks get called, you might consider defining a trait that describes all of them, and then they’ll all have access to Self: (Playground)


trait Callbacks {
    fn f1(&mut self);
    fn f2(&mut self);
}

fn gets_closures(cb: &mut impl Callbacks) {
    // do something 1
    cb.f1();
    // do something 2
    cb.f2();
    // do something 3
}

fn main() {
    struct Cb(usize);
    impl Callbacks for Cb {
        fn f1(&mut self) {
            self.0 += 1;
        }
        fn f2(&mut self) {
            self.0 += 2;
        }
    }

    let mut var = Cb(0);
    gets_closures(&mut var);

    println!("var: {}", var.0);
}
4 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.