1use std::{
2 rc::Rc,
3 cell::{
4 RefCell,
5 Ref,
6 RefMut
7 }
8};
9
10pub struct RcCell<A> {
11 value: Rc<RefCell<A>>
12}
13
14impl<A> Clone for RcCell<A> {
15 fn clone(&self) -> RcCell<A> {
16 let value = Rc::clone(&self.value);
17 RcCell {
18 value
19 }
20 }
21}
22
23impl<A> RcCell<A> {
24 pub fn new(value: A) -> RcCell<A> {
25 let value = RefCell::new(value);
26 let value = Rc::new(value);
27 RcCell {
28 value
29 }
30 }
31
32 pub fn borrow(&self) -> Ref<A> {
33 self.value.borrow()
34 }
35
36 pub fn borrow_mut(&self) -> RefMut<A> {
37 self.value.borrow_mut()
38 }
39
40 pub fn update(&self, u: fn(RefMut<A>)) {
41 u(self.borrow_mut())
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[derive(Debug, PartialEq)]
50 struct Data<A> {
51 value: A
52 }
53
54 impl<A> Data<A> {
55 fn new(value: A) -> Data<A> {
56 Data {
57 value,
58 }
59 }
60 }
61
62 #[test]
63 fn multiple_readers() {
64 let data: Data<i32> = Data::new(1);
65 let data = RcCell::new(data);
66
67 let clone1 = data.clone();
68 let clone2 = data.clone();
69
70 assert_eq!(clone1.borrow().value, 1);
71 assert_eq!(*clone1.borrow(), *clone2.borrow());
72 }
73
74 #[test]
75 fn multiple_writers() {
76 let data: Data<i32> = Data::new(1);
77 let data = RcCell::new(data);
78
79 let clone1 = data.clone();
80 clone1.update(|mut d| d.value += 1);
81 let clone2 = data.clone();
82 clone2.update(|mut d| d.value *= 3);
83
84 assert_eq!(data.borrow().value, 6);
85 assert_eq!(*clone1.borrow(), *clone2.borrow());
86 }
87
88 #[test]
89 fn example() {
90 #[derive(Debug, PartialEq)]
91 struct Data<A> {
92 value: A
93 }
94
95 impl<A> Data<A> {
96 fn new(value: A) -> Data<A> {
97 Data {
98 value,
99 }
100 }
101 }
102
103 let data: Data<i32> = Data::new(1);
104
105 let counter: RcCell<Data<i32>> = RcCell::new(data);
106 let counter_a: RcCell<Data<i32>> = counter.clone();
107 let counter_b: RcCell<Data<i32>> = counter.clone();
108
109 counter_a.update(|mut v| v.value += 1);
110 counter_b.borrow_mut().value *= 3;
111
112 assert_eq!(counter.borrow().value, 6);
113 assert_eq!(*counter_a.borrow(), *counter_b.borrow());
114 }
115}