1use std::any::TypeId;
2use std::cell::UnsafeCell;
3use std::collections::HashSet;
4use std::marker::PhantomData;
5
6use super::Invariant;
7
8std::thread_local! {
9 static SINGLETON_CHECK: std::cell::RefCell<HashSet<TypeId>> = std::cell::RefCell::new(HashSet::new());
10}
11
12struct NotSendOrSync(*const ());
13
14#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
19pub struct TLCellOwner<Q: 'static> {
20 not_send_or_sync: PhantomData<NotSendOrSync>,
22 typ: PhantomData<Invariant<Q>>,
24}
25
26impl<Q: 'static> Drop for TLCellOwner<Q> {
27 fn drop(&mut self) {
28 SINGLETON_CHECK.with(|set| set.borrow_mut().remove(&TypeId::of::<Q>()));
29 }
30}
31
32impl<Q: 'static> Default for TLCellOwner<Q> {
33 fn default() -> Self {
34 TLCellOwner::new()
35 }
36}
37
38impl<Q: 'static> TLCellOwner<Q> {
39 pub fn new() -> Self {
47 SINGLETON_CHECK.with(|set| {
48 assert!(set.borrow_mut().insert(TypeId::of::<Q>()),
49 "Illegal to create two TLCellOwner instances within the same thread with the same marker type parameter");
50 });
51 Self {
52 not_send_or_sync: PhantomData,
53 typ: PhantomData,
54 }
55 }
56
57 pub fn cell<T>(&self, value: T) -> TLCell<Q, T> {
62 TLCell::<Q, T>::new(value)
63 }
64
65 #[inline]
69 pub fn ro<'a, T: ?Sized>(&'a self, tc: &'a TLCell<Q, T>) -> &'a T {
70 unsafe { &*tc.value.get() }
71 }
72
73 #[inline]
78 pub fn rw<'a, T: ?Sized>(&'a mut self, tc: &'a TLCell<Q, T>) -> &'a mut T {
79 unsafe { &mut *tc.value.get() }
80 }
81
82 #[inline]
85 pub fn rw2<'a, T: ?Sized, U: ?Sized>(
86 &'a mut self,
87 tc1: &'a TLCell<Q, T>,
88 tc2: &'a TLCell<Q, U>,
89 ) -> (&'a mut T, &'a mut U) {
90 assert!(
91 tc1 as *const _ as *const () as usize != tc2 as *const _ as *const () as usize,
92 "Illegal to borrow same TLCell twice with rw2()"
93 );
94 unsafe { (&mut *tc1.value.get(), &mut *tc2.value.get()) }
95 }
96
97 #[inline]
100 pub fn rw3<'a, T: ?Sized, U: ?Sized, V: ?Sized>(
101 &'a mut self,
102 tc1: &'a TLCell<Q, T>,
103 tc2: &'a TLCell<Q, U>,
104 tc3: &'a TLCell<Q, V>,
105 ) -> (&'a mut T, &'a mut U, &'a mut V) {
106 assert!(
107 (tc1 as *const _ as *const () as usize != tc2 as *const _ as *const () as usize)
108 && (tc2 as *const _ as *const () as usize != tc3 as *const _ as *const () as usize)
109 && (tc3 as *const _ as *const () as usize != tc1 as *const _ as *const () as usize),
110 "Illegal to borrow same TLCell twice with rw3()"
111 );
112 unsafe {
113 (
114 &mut *tc1.value.get(),
115 &mut *tc2.value.get(),
116 &mut *tc3.value.get(),
117 )
118 }
119 }
120}
121
122#[repr(transparent)]
136#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
137pub struct TLCell<Q, T: ?Sized> {
138 owner: PhantomData<Invariant<Q>>,
140
141 value: UnsafeCell<T>,
155}
156
157impl<Q, T> TLCell<Q, T> {
158 #[inline]
161 pub const fn new(value: T) -> TLCell<Q, T> {
162 TLCell {
163 owner: PhantomData,
164 value: UnsafeCell::new(value),
165 }
166 }
167
168 #[inline]
173 pub fn into_inner(self) -> T {
174 self.value.into_inner()
175 }
176}
177
178impl<Q, T: ?Sized> TLCell<Q, T> {
179 #[inline]
183 pub fn ro<'a>(&'a self, owner: &'a TLCellOwner<Q>) -> &'a T {
184 owner.ro(self)
185 }
186
187 #[inline]
194 pub fn rw<'a>(&'a self, owner: &'a mut TLCellOwner<Q>) -> &'a mut T {
195 owner.rw(self)
196 }
197
198 #[inline]
210 pub fn get_mut(&mut self) -> &mut T {
211 self.value.get_mut()
212 }
213}
214
215impl<Q: 'static, T: Default + ?Sized> Default for TLCell<Q, T> {
216 fn default() -> Self {
217 TLCell::new(T::default())
218 }
219}
220
221#[cfg(test)]
222mod tests {
223 use super::{TLCell, TLCellOwner};
224
225 #[test]
226 #[should_panic]
227 fn tlcell_singleton_1() {
228 struct Marker;
229 let _owner1 = TLCellOwner::<Marker>::new();
230 let _owner2 = TLCellOwner::<Marker>::new(); }
232
233 #[test]
234 fn tlcell_singleton_2() {
235 struct Marker;
236 let owner1 = TLCellOwner::<Marker>::new();
237 drop(owner1);
238 let _owner2 = TLCellOwner::<Marker>::new();
239 }
240
241 #[test]
242 fn tlcell_singleton_3() {
243 struct Marker1;
244 struct Marker2;
245 let _owner1 = TLCellOwner::<Marker1>::new();
246 let _owner2 = TLCellOwner::<Marker2>::new();
247 }
248
249 #[test]
250 fn tlcell() {
251 struct Marker;
252 type ACellOwner = TLCellOwner<Marker>;
253 type ACell<T> = TLCell<Marker, T>;
254 let mut owner = ACellOwner::new();
255 let c1 = ACell::new(100u32);
256 let c2 = owner.cell(200u32);
257 (*owner.rw(&c1)) += 1;
258 (*owner.rw(&c2)) += 2;
259 let c1ref = owner.ro(&c1);
260 let c2ref = owner.ro(&c2);
261 let total = *c1ref + *c2ref;
262 assert_eq!(total, 303);
263 }
264
265 #[test]
266 fn tlcell_threads() {
267 struct Marker;
268 type ACellOwner = TLCellOwner<Marker>;
269 let mut _owner1 = ACellOwner::new();
270 std::thread::spawn(|| {
271 let mut _owner2 = ACellOwner::new();
272 })
273 .join()
274 .unwrap();
275 }
276
277 #[test]
278 fn tlcell_get_mut() {
279 struct Marker;
280 type ACellOwner = TLCellOwner<Marker>;
281 type ACell<T> = TLCell<Marker, T>;
282 let owner = ACellOwner::new();
283 let mut cell = ACell::new(100u32);
284 let mut_ref = cell.get_mut();
285 *mut_ref = 50;
286 let cell_ref = owner.ro(&cell);
287 assert_eq!(*cell_ref, 50);
288 }
289
290 #[test]
291 fn tlcell_into_inner() {
292 struct Marker;
293 type ACell<T> = TLCell<Marker, T>;
294 let cell = ACell::new(100u32);
295 assert_eq!(cell.into_inner(), 100);
296 }
297
298 #[test]
299 fn tlcell_unsized() {
300 struct Marker;
301 type ACellOwner = TLCellOwner<Marker>;
302 type ACell<T> = TLCell<Marker, T>;
303 let mut owner = ACellOwner::new();
304 struct Squares(u32);
305 struct Integers(u64);
306 trait Series {
307 fn step(&mut self);
308 fn value(&self) -> u64;
309 }
310 impl Series for Squares {
311 fn step(&mut self) {
312 self.0 += 1;
313 }
314 fn value(&self) -> u64 {
315 (self.0 as u64) * (self.0 as u64)
316 }
317 }
318 impl Series for Integers {
319 fn step(&mut self) {
320 self.0 += 1;
321 }
322 fn value(&self) -> u64 {
323 self.0
324 }
325 }
326 fn series(init: u32, is_squares: bool) -> Box<ACell<dyn Series>> {
327 if is_squares {
328 Box::new(ACell::new(Squares(init)))
329 } else {
330 Box::new(ACell::new(Integers(init as u64)))
331 }
332 }
333
334 let own = &mut owner;
335 let cell1 = series(4, false);
336 let cell2 = series(7, true);
337 let cell3 = series(3, true);
338 assert_eq!(cell1.ro(own).value(), 4);
339 cell1.rw(own).step();
340 assert_eq!(cell1.ro(own).value(), 5);
341 assert_eq!(own.ro(&cell2).value(), 49);
342 own.rw(&cell2).step();
343 assert_eq!(own.ro(&cell2).value(), 64);
344 let (r1, r2, r3) = own.rw3(&cell1, &cell2, &cell3);
345 r1.step();
346 r2.step();
347 r3.step();
348 assert_eq!(cell1.ro(own).value(), 6);
349 assert_eq!(cell2.ro(own).value(), 81);
350 assert_eq!(cell3.ro(own).value(), 16);
351 let (r1, r2) = own.rw2(&cell1, &cell2);
352 r1.step();
353 r2.step();
354 assert_eq!(cell1.ro(own).value(), 7);
355 assert_eq!(cell2.ro(own).value(), 100);
356 }
357}