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