/// make a ref-circle, it's possible in rust.
/// but rust make sure it safe.
use std::rc::Rc;
use std::cell::RefCell;
use crate::List::{Cons, Nil};
#[derive(Debug)]
enum List{
Cons(i32, RefCell<Rc<List>>),
Nil
}
impl List {
fn tail(&self) -> Option<&RefCell<Rc<List>>> {
match self {
Cons(_, item) => Some(item),
Nil => None,
}
}
}
fn main() {
let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
println!("a initial rc count = {}", Rc::strong_count(&a));
println!("a next item = {:?}", a.tail());
let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
println!("a rc count after b creation = {}", Rc::strong_count(&a));
println!("b initial rc count = {}", Rc::strong_count(&b));
println!("b next item = {:?}", b.tail());
if let Some(link) = a.tail() {
*link.borrow_mut() = Rc::clone(&b);
}
println!("b rc count after changing a = {}", Rc::strong_count(&b));
println!("a rc count after chaning a = {}", Rc::strong_count(&a));
/// Uncomment the next line to see that we have a cycle;
/// it will overflow the stack
//println!("a next item = {:?}", a.tail());
}
一般可以通过Weak来消除引用循环, Weak Ref通过Rc::downgrade创建,之后会增加并记录week_ref的count, 但是在strong_count为0时会清理数据. WeakRef通过 `rust`{Weak::upgrade() -> Option<Rc>}
use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Debug)]
struct Node {
value: i32,
parent: RefCell<Weak<Node>>,
children: RefCell<Vec<Rc<Node>>>,
}
fn main() {
let leaf = Rc::new(Node {
value: 3,
parent: RefCell::new(Weak:new()),
children: RefCell::new(vec![]),
});
println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
let branch = Rc::new(Node {
value: 5,
parent: RefCell::new(Weak::new()),
chidlren: RefCell::new(vec![Rc::clone(&self)]),
});
*leaf.parent.borrow_mut() = Rc::downgrade(&branch);
println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
}
visual strong_count
and weak_count
fn main() {
let leat = Rc::new(Node {
value: 3,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![]),
});
println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));
{
let branch = Rc::new(Node {
value: 5,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![Rc::clone(&self)]),
});
*leaf.parent.borrow_mut() = Rc::downgrade(&branch);
println!("branch strong = {}, weak = {}", Rc::strong_count(&branch), Rc::weak_count(&branch));
println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));
}
println!("branch strong = {}, weak = {}", Rc::strong_count(&branch), Rc::weak_count(&branch));
println!("leaf strong = {}, weak = {}", Rc::strong_count(&leaf), Rc::weak_count(&leaf));
}