diff --git a/.idea/misc.xml b/.idea/misc.xml index 98a09f5..55c8377 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -27,6 +27,7 @@ + diff --git a/.idea/rust.iml b/.idea/rust.iml index c67cafa..8165c4c 100644 --- a/.idea/rust.iml +++ b/.idea/rust.iml @@ -110,6 +110,10 @@ + + + + @@ -130,6 +134,7 @@ + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 1799341..c6ba616 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,7 +5,6 @@ - - - - - - - - - - - - - - - + - - + + @@ -108,6 +94,7 @@ @@ -141,12 +128,12 @@ - + - + @@ -180,7 +167,7 @@ - + @@ -208,7 +195,7 @@ - + + + - - + - @@ -330,8 +317,8 @@ - - + + @@ -339,7 +326,7 @@ - + @@ -749,9 +736,16 @@ + + + + + + + - + @@ -760,10 +754,10 @@ - + - - + + diff --git a/reference_cycles/Cargo.toml b/reference_cycles/Cargo.toml new file mode 100644 index 0000000..47ce1bc --- /dev/null +++ b/reference_cycles/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "reference_cycles" +version = "0.1.0" +authors = ["Timothy Warren "] +edition = "2018" + +[dependencies] diff --git a/reference_cycles/src/main.rs b/reference_cycles/src/main.rs new file mode 100644 index 0000000..be8ce31 --- /dev/null +++ b/reference_cycles/src/main.rs @@ -0,0 +1,98 @@ +use std::rc::{Rc, Weak}; +use std::cell::RefCell; +use List::{Cons, Nil}; + +#[derive(Debug)] +enum List { + Cons(i32, RefCell>), + Nil, +} + +impl List { + fn tail(&self) -> Option<&RefCell>> { + match self { + Cons(_, item) => Some(item), + Nil => None, + } + } +} + +fn cycle_example() { + 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 changing 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()); +} + +#[derive(Debug)] +struct Node { + value: i32, + parent: RefCell>, + children: RefCell>>, +} + +fn weakref_example() { + let leaf = 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(&leaf)]), + }); + + *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!("leaf parent = {:?}", leaf.parent.borrow().upgrade()); + println!( + "leaf strong = {}, weak = {}", + Rc::strong_count(&leaf), + Rc::weak_count(&leaf), + ); +} + +fn main() { + cycle_example(); + + weakref_example(); +}