|
| 1 | +#![allow(unused)] |
| 2 | + |
| 3 | +use std::cell::{RefCell, RefMut}; |
| 4 | +use std::rc::{Rc, Weak}; |
| 5 | + |
| 6 | +// Strong reference shares ownership |
| 7 | +// Weak reference breaks reference cycles and avoid memory leaks |
| 8 | + |
| 9 | +#[derive(Debug)] |
| 10 | + |
| 11 | +struct Node { |
| 12 | + val: u32, |
| 13 | + neighbors: RefCell<Vec<Weak<Node>>>, |
| 14 | +} |
| 15 | + |
| 16 | +fn main() { |
| 17 | + // Strong reference |
| 18 | + // Rc::clone -> strong_count increases |
| 19 | + // r0 is only dropped when strong_count is 0 |
| 20 | + let x = "hello".to_string(); |
| 21 | + |
| 22 | + let r0: Rc<String> = Rc::new(x); |
| 23 | + println!("r0 - strong count: {}", Rc::strong_count(&r0)); |
| 24 | + |
| 25 | + let r1 = Rc::clone(&r0); |
| 26 | + println!("r1 - strong count: {}", Rc::strong_count(&r0)); |
| 27 | + |
| 28 | + // Weak refenence |
| 29 | + // Rc::downgrade -> weak_count increases |
| 30 | + // Rc::upgrade -> returns Option<Rc<T>>` |
| 31 | + let w1: Weak<String> = Rc::downgrade(&r0); |
| 32 | + println!("w1 - strong count: {}", Rc::strong_count(&r0)); |
| 33 | + println!("w1 - weak count: {}", Rc::weak_count(&r0)); |
| 34 | + |
| 35 | + let w2: Weak<String> = Rc::downgrade(&r0); |
| 36 | + println!("w2 - strong count: {}", Rc::strong_count(&r0)); |
| 37 | + println!("w2 - weak count: {}", Rc::weak_count(&r0)); |
| 38 | + |
| 39 | + // Upgrade weak to strong reference |
| 40 | + let u0 = w1.upgrade(); |
| 41 | + println!("u0 - upgrade w1: {:?}", u0); |
| 42 | + println!("u0 - strong count: {}", Rc::strong_count(&r0)); |
| 43 | + println!("u0 - weak count: {}", Rc::weak_count(&r0)); |
| 44 | + |
| 45 | + // Drop some strong references |
| 46 | + println!("drop u0 and r1"); |
| 47 | + std::mem::drop(u0); |
| 48 | + std::mem::drop(r1); |
| 49 | + |
| 50 | + let u1 = w1.upgrade(); |
| 51 | + println!("u1 - upgrade w1: {:?}", u1); |
| 52 | + println!("u1 - strong count: {}", Rc::strong_count(&r0)); |
| 53 | + println!("u1 - weak count: {}", Rc::weak_count(&r0)); |
| 54 | + |
| 55 | + // Drop all strong references |
| 56 | + println!("drop u1 and r0"); |
| 57 | + std::mem::drop(u1); |
| 58 | + std::mem::drop(r0); |
| 59 | + |
| 60 | + let u2 = w1.upgrade(); |
| 61 | + println!("u2 - upgrade w1: {:?}", u2); |
| 62 | + |
| 63 | + // Example - Node |
| 64 | + let node0 = Rc::new(Node { |
| 65 | + val: 0, |
| 66 | + neighbors: RefCell::new(vec![]), |
| 67 | + }); |
| 68 | + let node1 = Rc::new(Node { |
| 69 | + val: 1, |
| 70 | + neighbors: RefCell::new(vec![]), |
| 71 | + }); |
| 72 | + |
| 73 | + // Create a cycle |
| 74 | + // node 0 -> node 1 |
| 75 | + // node 1 -> node 0 |
| 76 | + { |
| 77 | + // Rc::clone increments strong_count by 1. |
| 78 | + // Rc<T> cannot be dropped unless strong_count is 0. |
| 79 | + // Since node 0 and node 1 references each other, their strong_count can never reach 0. |
| 80 | + // Hence neither node 0 nor node 1 can ever be dropped. |
| 81 | + |
| 82 | + // Weak<T> does not increment strong_count. |
| 83 | + // Hence both node 0 and 1 can be dropped. |
| 84 | + |
| 85 | + // node 0 -> node 1 |
| 86 | + let mut r0: RefMut<'_, Vec<Weak<Node>>> = node0.neighbors.borrow_mut(); |
| 87 | + r0.push(Rc::downgrade(&node1)); |
| 88 | + |
| 89 | + // node 1 -> node 0 |
| 90 | + let mut r1: RefMut<'_, Vec<Weak<Node>>> = node1.neighbors.borrow_mut(); |
| 91 | + r1.push(Rc::downgrade(&node0)); |
| 92 | + } |
| 93 | + |
| 94 | + // No infinite loop |
| 95 | + println!("{:#?}", node0); |
| 96 | + |
| 97 | + // Print node1 - prints Some(Node) |
| 98 | + println!( |
| 99 | + "{:#?}", |
| 100 | + node0 |
| 101 | + .neighbors |
| 102 | + .borrow() |
| 103 | + .get(0) |
| 104 | + .map(|weak_ref| weak_ref.upgrade()) |
| 105 | + ); |
| 106 | + |
| 107 | + // Drop node1 |
| 108 | + std::mem::drop(node1); |
| 109 | + |
| 110 | + // Print node1 - prints None |
| 111 | + println!( |
| 112 | + "{:#?}", |
| 113 | + node0 |
| 114 | + .neighbors |
| 115 | + .borrow() |
| 116 | + .get(0) |
| 117 | + .map(|weak_ref| weak_ref.upgrade()) |
| 118 | + ); |
| 119 | +} |
0 commit comments