radiate_core/domain/sync/
cell.rs1use std::{
2 cell::UnsafeCell,
3 fmt::{Debug, Formatter},
4 ops::Deref,
5 sync::atomic::{AtomicUsize, Ordering},
6};
7
8pub struct MutCell<T> {
9 inner: *const ArcInner<T>,
10 consumed: bool,
11}
12
13struct ArcInner<T> {
14 value: UnsafeCell<T>,
15 ref_count: AtomicUsize,
16}
17
18unsafe impl<T: Send> Send for MutCell<T> {}
20unsafe impl<T: Sync> Sync for MutCell<T> {}
21
22impl<T> MutCell<T> {
23 pub fn new(value: T) -> Self {
24 Self {
25 inner: Box::into_raw(Box::new(ArcInner {
26 value: UnsafeCell::new(value),
27 ref_count: AtomicUsize::new(1),
28 })),
29 consumed: false,
30 }
31 }
32
33 pub fn is_unique(&self) -> bool {
34 unsafe { (*self.inner).ref_count.load(Ordering::Acquire) == 1 }
36 }
37
38 pub fn is_shared(&self) -> bool {
39 !self.is_unique()
40 }
41
42 pub fn strong_count(&self) -> usize {
43 unsafe { (*self.inner).ref_count.load(Ordering::Acquire) }
45 }
46
47 pub fn borrow(&self) -> &T {
48 assert!(!self.consumed, "Cannot access consumed MutCell");
55 unsafe { &*(*self.inner).value.get() }
56 }
57
58 pub fn borrow_mut(&mut self) -> &mut T {
59 assert!(self.is_unique(), "Cannot mutably borrow shared MutCell");
60 unsafe { &mut *(*self.inner).value.get() }
61 }
62
63 pub fn into_inner(mut self) -> T
64 where
65 T: Clone,
66 {
67 unsafe {
72 if (*self.inner).ref_count.load(Ordering::Acquire) == 1 {
73 self.consumed = true;
74 std::sync::atomic::fence(Ordering::SeqCst);
75 let boxed = Box::from_raw(self.inner as *mut ArcInner<T>);
76 boxed.value.into_inner()
77 } else {
78 let clone = (*(*self.inner).value.get()).clone();
79 (*self.inner).ref_count.fetch_sub(1, Ordering::Release);
80 clone
81 }
82 }
83 }
84}
85
86impl<T> Clone for MutCell<T> {
87 fn clone(&self) -> Self {
88 unsafe {
89 (*self.inner).ref_count.fetch_add(1, Ordering::Relaxed);
90 }
91 Self {
92 inner: self.inner,
93 consumed: false,
94 }
95 }
96}
97
98impl<T> Drop for MutCell<T> {
99 fn drop(&mut self) {
100 if self.consumed {
101 return;
102 }
103
104 unsafe {
105 if (*self.inner).ref_count.fetch_sub(1, Ordering::Release) == 1 {
106 std::sync::atomic::fence(Ordering::Acquire);
107 drop(Box::from_raw(self.inner as *mut ArcInner<T>));
108 }
109 }
110 }
111}
112
113impl<T> Deref for MutCell<T> {
114 type Target = T;
115 fn deref(&self) -> &Self::Target {
116 self.borrow()
117 }
118}
119
120impl<T: PartialEq> PartialEq for MutCell<T> {
121 fn eq(&self, other: &Self) -> bool {
122 self.borrow() == other.borrow()
123 }
124}
125
126impl<T: PartialOrd> PartialOrd for MutCell<T> {
127 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
128 self.borrow().partial_cmp(other.borrow())
129 }
130}
131
132impl<T> From<T> for MutCell<T> {
133 fn from(value: T) -> Self {
134 Self::new(value)
135 }
136}
137
138impl<T: Debug> Debug for MutCell<T> {
139 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
140 write!(f, "{:?}", self.borrow())
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn mutcell_basic_clone_and_mutation_updated() {
150 let mut cell = MutCell::new(5);
151 assert_eq!(*cell, 5);
152
153 *cell.borrow_mut() = 10;
155 assert_eq!(*cell, 10);
156
157 let cell2 = cell.clone();
159 assert_eq!(*cell2, 10);
162 }
163
164 #[test]
165 fn mutcell_into_inner_unique() {
166 let cell = MutCell::new(String::from("hello"));
167 let inner = cell.into_inner();
168 assert_eq!(inner, "hello");
169 }
170
171 #[test]
172 fn mutcell_into_inner_clone_when_multiple() {
173 let cell = MutCell::new(String::from("hello"));
174 let cell2 = cell.clone();
175
176 let inner = cell.into_inner();
177 assert_eq!(inner, "hello");
178
179 drop(cell2);
181 }
182
183 #[test]
184 fn mutcell_partial_eq_and_ord() {
185 let cell1 = MutCell::new(10);
186 let cell2 = MutCell::new(20);
187 let cell3 = MutCell::new(10);
188
189 assert!(cell1 == cell3);
190 assert!(cell1 != cell2);
191 assert!(cell1 < cell2);
192 assert!(cell2 > cell3);
193 }
194
195 #[test]
196 fn mutcell_is_unique_and_shared() {
197 let cell = MutCell::new(42);
198 assert!(cell.is_unique());
199
200 let cell2 = cell.clone();
201
202 assert!(cell.is_shared());
203 assert!(cell2.is_shared());
204 assert!(!cell.is_unique());
205 assert!(!cell2.is_unique());
206 assert_eq!(*cell, 42);
207 assert_eq!(*cell2, 42);
208 assert!(cell.borrow() == cell2.borrow());
209 }
210
211 #[test]
212 fn mut_cell_drop() {
213 let cell = MutCell::new(42);
214 {
215 let _cell2 = cell.clone();
216 assert!(cell.is_shared());
217 } assert!(cell.is_unique());
220 drop(cell); }
222
223 #[test]
224 fn mut_cell_deref() {
225 let mut cell = MutCell::new(42);
226 assert_eq!(*cell, 42);
227 let mut_ref = cell.borrow_mut();
228 *mut_ref = 100;
229 assert_eq!(*cell, 100);
230 }
231}