I want to have a
set of functions to operate on a given structure. Two CPUs need to access
one single mutable memory.
From what I've read, I need Rc<RefCell<_>>.
This is akin to the problem of the representing a tree
but it is simpler since my structs have relationships defined at compile time and don't need to be generic.
The code below works, but I wonder if it is idiomatic. Coming from OOP background, I find it quite problematic:
Although the
memoryfield is present in theCpustruct, I have to apply aborrow_mut()on it each time I need to access it in theimpl. Is this because Rust wants me to avoid two simultaneous mutable references?I have to pass the
memparameter to thedo_stufffunction. If I have dozens of nested functions I'll have to pass that parameter on each call. Is it possible to avoid that?If I pass that parameter around, then it'd be just as simple to not have the memory field in the
Cpustruct, and just passingmut &Memoryreferences around instead which questions the need for theRc<RefCell<Memory>>construct...
Code sample:
use std::cell::{RefCell, RefMut};
use std::rc::Rc;
struct Cpu {
memory: Rc<RefCell<Memory>>
}
impl Cpu {
fn new(m : Rc<RefCell<Memory>>) -> Cpu {
Cpu { memory: m } }
fn run(&mut self) {
self.do_stuff(self.memory.borrow_mut());
// Show repetition of borrow_mut (point 1)
self.do_stuff(self.memory.borrow_mut());
}
// Show the need for mem parameter (point 2)
fn do_stuff(&self, mut mem: RefMut<Memory>) {
let i = mem.load(4) + 10;
mem.set(4, i);
}
}
struct Memory { pub mem: [u8; 5] }
impl Memory {
fn new() -> Memory { Memory { mem: [0 as u8; 5] } }
fn load( &self, ndx : usize) -> u8 { self.mem[ndx] }
fn set( &mut self, ndx : usize, val: u8) { self.mem[ndx] = val }
}
fn main() {
let memory: Rc<RefCell<_>> = Rc::new(RefCell::new(Memory::new()));
let mut cpu1 = Cpu::new(memory.clone());
let mut cpu2 = Cpu::new(memory.clone());
cpu1.run();
cpu2.run();
println!("{}",memory.borrow().mem[4]);
}