study_example/smart_pointer/
reference_cycle.rs

1use crate::smart_pointer::reference_cycle::List::{Cons, Nil};
2use std::cell::RefCell;
3use std::rc::{Rc, Weak};
4
5#[derive(Debug)]
6enum List {
7    Cons(i32, RefCell<Rc<List>>),
8    Nil,
9}
10
11impl List {
12    fn tail(&self) -> Option<&RefCell<Rc<List>>> {
13        match self {
14            Cons(_, item) => Some(item),
15            Nil => None,
16        }
17    }
18}
19
20/// 运行结果如下
21/// ```txt
22/// a initial rc count = 1
23/// a next item = Some(RefCell { value: Nil })
24/// after b create a rc count = 2
25/// b init rc count = 1
26/// b next item = Some(RefCell { value: Cons(5, RefCell { value: Nil }) })
27/// after changing a: b rc count = 2
28/// after changing a: a rc count = 2
29/// ```
30fn create_reference_cycle() {
31    let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
32    println!("a initial rc count = {}", Rc::strong_count(&a));
33    println!("a next item = {:?}", a.tail());
34    let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
35    println!("after b create a rc count = {}", Rc::strong_count(&a));
36    println!("b init rc count = {}", Rc::strong_count(&b));
37    println!("b next item = {:?}", b.tail());
38
39    if let Some(link) = a.tail() {
40        *link.borrow_mut() = Rc::clone(&b);
41    }
42    println!("after changing a: b rc count = {}", Rc::strong_count(&b));
43    println!("after changing a: a rc count = {}", Rc::strong_count(&a));
44    // thread 'main' has overflowed its stack
45    // fatal runtime error: stack overflow
46    // println!("a next item = {:?}", a.tail());
47}
48
49#[derive(Debug)]
50struct Node {
51    value: i32,
52    parent: RefCell<Weak<Node>>,
53    children: RefCell<Vec<Rc<Node>>>,
54}
55
56/// 运行结果如下
57/// ```txt
58/// leaf Rc strong_count = 1, weak = 0
59/// leaf parent = None
60/// baranch strong_count = 1, weak = 1
61/// leaf after branch Rc strong_count = 2, weak = 0
62/// leaf parent = Some(Node { value: 5, parent: RefCell { value: (Weak) }, children: RefCell { value: [Node { value: 3, parent: RefCell { value: (Weak) }, children: RefCell { value: [] } }] } })
63/// leaf after borrow Rc strong_count = 1, weak = 0
64///
65fn weak_to_avoid_reference_cycle() {
66    let leaf = Rc::new(Node {
67        value: 3,
68        parent: RefCell::new(Weak::new()),
69        children: RefCell::new(vec![]),
70    });
71    println!(
72        "leaf Rc strong_count = {}, weak = {}",
73        Rc::strong_count(&leaf),
74        Rc::weak_count(&leaf)
75    );
76    println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
77    {
78        let branch = Rc::new(Node {
79            value: 5,
80            parent: RefCell::new(Weak::new()),
81            children: RefCell::new(vec![Rc::clone(&leaf)]),
82        });
83        *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
84        println!(
85            "baranch strong_count = {}, weak = {}",
86            Rc::strong_count(&branch),
87            Rc::weak_count(&branch)
88        );
89        println!(
90            "leaf after branch Rc strong_count = {}, weak = {}",
91            Rc::strong_count(&leaf),
92            Rc::weak_count(&leaf)
93        );
94        println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
95    }
96    println!(
97        "leaf after borrow Rc strong_count = {}, weak = {}",
98        Rc::strong_count(&leaf),
99        Rc::weak_count(&leaf)
100    );
101}
102
103pub fn reference_cycle_study() {
104    create_reference_cycle();
105    weak_to_avoid_reference_cycle();
106}