I am trying to hold multiple callbacks as closures, but I'm having troubles with their lifetime:
pub type WriteCallback = Box<dyn FnMut(u8, u8) -> u8>;
pub struct AddressBus {
on_write_listeners: HashMap<usize, WriteCallback>,
}
impl AddressBus {
pub fn on_write(&mut self, address: usize, callback: WriteCallback) {
self.on_write_listeners.insert(address, callback);
}
}
// component.rs
pub struct Component {
value: u8,
address_bus: Rc<RefCell<AddressBus>>,
}
impl Component {
pub fn new(address_bus: Rc<RefCell<AddressBus>>) -> Self {
Component {
value: 0,
address_bus: address_bus.clone(),
}
}
pub fn init(&mut self) {
self.address_bus.clone().borrow_mut().on_write(0xFF54, Box::new(|old, new| {
// I want to use self here e.g: self.value = new;
new
}));
self.address_bus.clone().borrow_mut().on_write(0xFF55, Box::new(|old, new| {
// I want to use self here
new
}));
}
}
But no matter what i try, i always get:
32 | pub fn init(&mut self) {
| - let's call the lifetime of this reference `'1`
33 | self.address_bus.clone().borrow_mut().on_write(0xFF54, Box::new(|old, new| {
| ________________________________________________________________^
34 | | // I want to use self here
35 | | self.value = new;
36 | | new
37 | | }));
| |__________^ cast requires that `'1` must outlive `'static`
Is there a way to fix this, or do I need to change to a different design pattern? Knowing that I am using wasm-bindgen and can't use lifetime references inside my structures.
I tried to use move
like self.address_bus.clone().borrow_mut().on_write(0xFF54, Box::new(move ...
. It works but it also consumes self
and I am no longer able to use the struct.
I managed to make it work by following cdhowie's advice, using Rc<RefCell<Self>>
:
fn init(rc: Rc<RefCell<Self>>) {
let rc2 = rc.clone();
rc.clone().borrow_mut().address_bus.borrow_mut().on_write(0xFF54, Box::new(move |old, new| {
new
}));
rc2.clone().borrow_mut().address_bus.borrow_mut().on_write(0xFF55, Box::new(move |old, new| {
rc2.borrow_mut().value = old;
new
}));
}
In order to modify self
in both, I need to clone the reference and move it.