shadow_shim_helper_rs/rootedcell/
cell.rs
1use std::cell::UnsafeCell;
2
3use vasi::VirtualAddressSpaceIndependent;
4
5use super::{Root, Tag};
6
7#[derive(Debug, VirtualAddressSpaceIndependent)]
15#[repr(C)]
16pub struct RootedCell<T> {
17 tag: Tag,
18 val: UnsafeCell<T>,
19}
20
21impl<T> RootedCell<T> {
22 #[inline]
24 pub fn new(root: &Root, val: T) -> Self {
25 Self {
26 tag: root.tag(),
27 val: UnsafeCell::new(val),
28 }
29 }
30
31 #[inline]
32 pub fn get_mut(&mut self) -> &mut T {
33 unsafe { &mut *self.val.get() }
35 }
36
37 #[inline]
38 pub fn set(&self, root: &Root, val: T) {
39 drop(self.replace(root, val))
41 }
42
43 #[inline]
44 pub fn replace(&self, root: &Root, val: T) -> T {
45 assert_eq!(
47 root.tag, self.tag,
48 "Expected {:?} Got {:?}",
49 self.tag, root.tag
50 );
51
52 unsafe { self.val.get().replace(val) }
53 }
54
55 #[inline]
56 pub fn into_inner(self) -> T {
57 self.val.into_inner()
58 }
59}
60
61impl<T: Copy> RootedCell<T> {
62 #[inline]
63 pub fn get(&self, root: &Root) -> T {
64 assert_eq!(
66 root.tag, self.tag,
67 "Expected {:?} Got {:?}",
68 self.tag, root.tag
69 );
70
71 unsafe { *self.val.get() }
72 }
73}
74
75unsafe impl<T: Send> Send for RootedCell<T> where T: Copy {}
76unsafe impl<T: Send> Sync for RootedCell<T> where T: Copy {}
77
78#[cfg(test)]
79mod test_rooted_cell {
80 use std::thread;
81
82 use super::*;
83 use crate::explicit_drop::ExplicitDrop;
84 use crate::rootedcell::rc::RootedRc;
85
86 #[test]
87 fn get() {
88 let root = Root::new();
89 let c = RootedCell::new(&root, 1);
90 assert_eq!(c.get(&root), 1);
91 }
92
93 #[test]
94 fn get_mut() {
95 let root = Root::new();
96 let mut c = RootedCell::new(&root, 1);
97 assert_eq!(*c.get_mut(), 1);
98 }
99
100 #[test]
101 fn set() {
102 let root = Root::new();
103 let c = RootedCell::new(&root, 1);
104 c.set(&root, 2);
105 assert_eq!(c.get(&root), 2);
106 }
107
108 #[test]
109 fn replace() {
110 let root = Root::new();
111 let c = RootedCell::new(&root, 1);
112 let old = c.replace(&root, 2);
113 assert_eq!(old, 1);
114 assert_eq!(c.get(&root), 2);
115 }
116
117 #[test]
118 fn share_with_worker_thread() {
119 let root = Root::new();
120 let rc = RootedRc::new(&root, RootedCell::new(&root, 0));
121 let root = {
122 let rc = { rc.clone(&root) };
123 thread::spawn(move || {
124 rc.set(&root, 3);
125 rc.explicit_drop(&root);
126 root
127 })
128 .join()
129 .unwrap()
130 };
131 assert_eq!(rc.get(&root), 3);
132 rc.explicit_drop(&root);
133 }
134
135 #[test]
136 fn worker_thread_get_mut() {
137 let root = Root::new();
138 let cell = RootedCell::new(&root, 0);
139 let cell = {
140 thread::spawn(move || {
141 let mut cell = cell;
143 *cell.get_mut() = 3;
146 cell
148 })
149 .join()
150 .unwrap()
151 };
152 assert_eq!(cell.get(&root), 3);
153 }
154}