shadow_shim_helper_rs/rootedcell/
refcell.rs
1use std::cell::{Cell, UnsafeCell};
2
3use vasi::VirtualAddressSpaceIndependent;
4
5use crate::explicit_drop::ExplicitDrop;
6
7use super::{Root, Tag};
8
9#[derive(Debug, VirtualAddressSpaceIndependent)]
17#[repr(C)]
18pub struct RootedRefCell<T> {
19 tag: Tag,
20 val: UnsafeCell<T>,
21 reader_count: Cell<u32>,
22 writer: Cell<bool>,
23}
24
25impl<T> RootedRefCell<T> {
26 #[inline]
28 pub fn new(root: &Root, val: T) -> Self {
29 Self {
30 tag: root.tag(),
31 val: UnsafeCell::new(val),
32 reader_count: Cell::new(0),
33 writer: Cell::new(false),
34 }
35 }
36
37 #[inline]
40 pub fn borrow<'a>(&'a self, root: &'a Root) -> RootedRefCellRef<'a, T> {
41 assert_eq!(
43 root.tag, self.tag,
44 "Expected {:?} Got {:?}",
45 self.tag, root.tag
46 );
47
48 assert!(!self.writer.get());
49
50 self.reader_count.set(self.reader_count.get() + 1);
51
52 RootedRefCellRef { guard: self }
53 }
54
55 #[inline]
58 pub fn borrow_mut<'a>(&'a self, root: &'a Root) -> RootedRefCellRefMut<'a, T> {
59 assert_eq!(
61 root.tag, self.tag,
62 "Expected {:?} Got {:?}",
63 self.tag, root.tag
64 );
65
66 assert!(!self.writer.get());
67 assert!(self.reader_count.get() == 0);
68
69 self.writer.set(true);
70
71 RootedRefCellRefMut { guard: self }
72 }
73
74 #[inline]
75 pub fn into_inner(self) -> T {
76 self.val.into_inner()
77 }
78}
79
80unsafe impl<T: Send> Send for RootedRefCell<T> {}
81unsafe impl<T: Send> Sync for RootedRefCell<T> {}
82
83impl<T> ExplicitDrop for RootedRefCell<T>
84where
85 T: ExplicitDrop,
86{
87 type ExplicitDropParam = <T as ExplicitDrop>::ExplicitDropParam;
88 type ExplicitDropResult = <T as ExplicitDrop>::ExplicitDropResult;
89
90 fn explicit_drop(self, param: &Self::ExplicitDropParam) -> Self::ExplicitDropResult {
91 self.val.into_inner().explicit_drop(param)
92 }
93}
94
95pub struct RootedRefCellRef<'a, T> {
96 guard: &'a RootedRefCell<T>,
97}
98
99impl<T> std::ops::Deref for RootedRefCellRef<'_, T> {
100 type Target = T;
101
102 #[inline]
103 fn deref(&self) -> &Self::Target {
104 unsafe { self.guard.val.get().as_ref().unwrap() }
105 }
106}
107
108impl<T> Drop for RootedRefCellRef<'_, T> {
109 #[inline]
110 fn drop(&mut self) {
111 self.guard
112 .reader_count
113 .set(self.guard.reader_count.get() - 1);
114 }
115}
116
117pub struct RootedRefCellRefMut<'a, T> {
118 guard: &'a RootedRefCell<T>,
119}
120
121impl<T> std::ops::Deref for RootedRefCellRefMut<'_, T> {
122 type Target = T;
123
124 #[inline]
125 fn deref(&self) -> &Self::Target {
126 unsafe { self.guard.val.get().as_ref().unwrap() }
127 }
128}
129
130impl<T> std::ops::DerefMut for RootedRefCellRefMut<'_, T> {
131 #[inline]
132 fn deref_mut(&mut self) -> &mut Self::Target {
133 unsafe { self.guard.val.get().as_mut().unwrap() }
134 }
135}
136
137impl<T> Drop for RootedRefCellRefMut<'_, T> {
138 #[inline]
139 fn drop(&mut self) {
140 self.guard.writer.set(false);
141 }
142}
143
144#[cfg(test)]
145mod test_rooted_refcell {
146 use std::thread;
147
148 use super::*;
149 use crate::explicit_drop::ExplicitDrop;
150 use crate::rootedcell::rc::RootedRc;
151
152 #[test]
153 fn construct_and_drop() {
154 let root = Root::new();
155 let _ = RootedRefCell::new(&root, 0);
156 }
157
158 #[test]
159 fn share_with_worker_thread() {
160 let root = Root::new();
161 let rc = RootedRc::new(&root, RootedRefCell::new(&root, 0));
162 let root = {
163 let rc = { rc.clone(&root) };
164 thread::spawn(move || {
165 let mut borrow = rc.borrow_mut(&root);
166 *borrow = 3;
167 drop(borrow);
169 rc.explicit_drop(&root);
170 root
171 })
172 .join()
173 .unwrap()
174 };
175 let borrow = rc.borrow(&root);
176 assert_eq!(*borrow, 3);
177 drop(borrow);
178 rc.explicit_drop(&root);
179 }
180}