I'm trying to convert some object oriented code into Rust. It was going okay until I ran into this situation.
struct A {
root: Rc<RefCell<B>>,
}
struct B {
parent: Weak<RefCell<B>>,
c_lst: Vec<C>
value: u32
}
struct C {
parent: Weak<RefCell<B>>,
b_lst: Vec<Rc<RefCell<B>>>,
end: bool
}
I have three structs. I want to have a main struct (A
here) hold a root of struct B
. B
and C
need to access parent values as read only, but where the first Rc
occurs they need to be mutable.
At start this function is called:
impl A {
fn register(&mut self) {
for c in self.root.borrow_mut().c_lst {
c.parent = Rc::downgrade(&self.root);
}
}
}
Then I use an update function on A
:
impl A {
fn update(&mut self) {
self.root.borrow_mut().update();
}
}
impl B {
fn update(&mut self) {
for c in &mut self.c_lst {
c.update();
}
}
}
impl C {
fn update(&mut self) {
match self.parent.upgrade() {
Some(parent) => {
// Fail because parent is already borrowed to call this update
if parent.try_borrow().unwrap().value == 0 {
// Do stuff
}
},
None => Panic!("Parent was freed")
}
if some_condition {
self.spawn_b();
}
for b in &self.b_lst {
b.borrow_mut().update();
}
}
// This infinite loop in this state, but it's for the example
fn spawn_b(&mut self) {
let b = Rc::new(RefCell::new(B::new()));
b.borrow_mut().parent = self.parent.clone();
if !self.end {
b.borrow_mut().c_lst = vec![C::new(Rc::downgrade(&b)), C::new(Rc::downgrade(&b))];
for c in b.borrow_mut().c {
c.spawn_b();
}
}
self.b_lst.push(b);
}
}
As you see in the code, I can't access my parent state. Any suggestions?
The Rc/Weak tree in your example is a straightforward way to implement trees with parent references in Rust. The only issue is that your update
function requires mutable access to the node its updating, which locks out the lower nodes from accessing the parent.
You're going to have to make an architectural change to solve this. A couple ways of doing it:
RefCell
s or even Cell
s. Lock the main data while your own node is updating, then unlock it before recursing through the children, letting them have access.