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
12#[allow(dead_code)]
13struct NotSendOrSync(*const ());
14
15#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
20pub struct TLCellOwner<Q: 'static> {
21 not_send_or_sync: PhantomData<NotSendOrSync>,
23 typ: PhantomData<Invariant<Q>>,
25}
26
27impl<Q: 'static> Drop for TLCellOwner<Q> {
28 fn drop(&mut self) {
29 SINGLETON_CHECK.with(|set| set.borrow_mut().remove(&TypeId::of::<Q>()));
30 }
31}
32
33impl<Q: 'static> Default for TLCellOwner<Q> {
34 fn default() -> Self {
35 TLCellOwner::new()
36 }
37}
38
39impl<Q: 'static> TLCellOwner<Q> {
40 pub fn new() -> Self {
48 if let Some(owner) = Self::try_new() {
49 owner
50 } else {
51 panic!("Illegal to create two TLCellOwner instances within the same thread with the same marker type parameter");
52 }
53 }
54
55 pub fn try_new() -> Option<Self> {
59 if SINGLETON_CHECK.with(|set| set.borrow_mut().insert(TypeId::of::<Q>())) {
60 Some(Self {
61 not_send_or_sync: PhantomData,
62 typ: PhantomData,
63 })
64 } else {
65 None
66 }
67 }
68
69 pub fn cell<T>(&self, value: T) -> TLCell<Q, T> {
74 TLCell::<Q, T>::new(value)
75 }
76
77 #[inline]
81 pub fn ro<'a, T: ?Sized>(&'a self, tc: &'a TLCell<Q, T>) -> &'a T {
82 unsafe { &*tc.value.get() }
83 }
84
85 #[inline]
90 pub fn rw<'a, T: ?Sized>(&'a mut self, tc: &'a TLCell<Q, T>) -> &'a mut T {
91 unsafe { &mut *tc.value.get() }
92 }
93
94 #[inline]
97 pub fn rw2<'a, T: ?Sized, U: ?Sized>(
98 &'a mut self,
99 tc1: &'a TLCell<Q, T>,
100 tc2: &'a TLCell<Q, U>,
101 ) -> (&'a mut T, &'a mut U) {
102 assert!(
103 !core::ptr::eq(tc1 as *const _ as *const (), tc2 as *const _ as *const ()),
104 "Illegal to borrow same TLCell twice with rw2()"
105 );
106 unsafe { (&mut *tc1.value.get(), &mut *tc2.value.get()) }
107 }
108
109 #[inline]
112 pub fn rw3<'a, T: ?Sized, U: ?Sized, V: ?Sized>(
113 &'a mut self,
114 tc1: &'a TLCell<Q, T>,
115 tc2: &'a TLCell<Q, U>,
116 tc3: &'a TLCell<Q, V>,
117 ) -> (&'a mut T, &'a mut U, &'a mut V) {
118 assert!(
119 !core::ptr::eq(tc1 as *const _ as *const (), tc2 as *const _ as *const ())
120 && !core::ptr::eq(tc2 as *const _ as *const (), tc3 as *const _ as *const ())
121 && !core::ptr::eq(tc3 as *const _ as *const (), tc1 as *const _ as *const ()),
122 "Illegal to borrow same TLCell twice with rw3()"
123 );
124 unsafe {
125 (
126 &mut *tc1.value.get(),
127 &mut *tc2.value.get(),
128 &mut *tc3.value.get(),
129 )
130 }
131 }
132}
133
134#[repr(transparent)]
148#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
149pub struct TLCell<Q, T: ?Sized> {
150 owner: PhantomData<Invariant<Q>>,
152
153 value: UnsafeCell<T>,
167}
168
169impl<Q, T> TLCell<Q, T> {
170 #[inline]
173 pub const fn new(value: T) -> TLCell<Q, T> {
174 TLCell {
175 owner: PhantomData,
176 value: UnsafeCell::new(value),
177 }
178 }
179
180 #[inline]
185 pub fn into_inner(self) -> T {
186 self.value.into_inner()
187 }
188}
189
190impl<Q, T: ?Sized> TLCell<Q, T> {
191 #[inline]
195 pub fn ro<'a>(&'a self, owner: &'a TLCellOwner<Q>) -> &'a T {
196 owner.ro(self)
197 }
198
199 #[inline]
206 pub fn rw<'a>(&'a self, owner: &'a mut TLCellOwner<Q>) -> &'a mut T {
207 owner.rw(self)
208 }
209
210 #[inline]
222 pub fn get_mut(&mut self) -> &mut T {
223 self.value.get_mut()
224 }
225}
226
227impl<Q: 'static, T: Default> Default for TLCell<Q, T> {
228 fn default() -> Self {
229 TLCell::new(T::default())
230 }
231}
232
233#[cfg(test)]
234mod tests {
235 use super::{TLCell, TLCellOwner};
236
237 #[test]
238 #[should_panic]
239 fn tlcell_singleton_1() {
240 struct Marker;
241 let _owner1 = TLCellOwner::<Marker>::new();
242 let _owner2 = TLCellOwner::<Marker>::new(); }
244
245 #[test]
246 fn tlcell_singleton_2() {
247 struct Marker;
248 let owner1 = TLCellOwner::<Marker>::new();
249 drop(owner1);
250 let _owner2 = TLCellOwner::<Marker>::new();
251 }
252
253 #[test]
254 fn tlcell_singleton_3() {
255 struct Marker1;
256 struct Marker2;
257 let _owner1 = TLCellOwner::<Marker1>::new();
258 let _owner2 = TLCellOwner::<Marker2>::new();
259 }
260
261 #[test]
262 fn tlcell_singleton_try_new() {
263 struct Marker;
264 let owner1 = TLCellOwner::<Marker>::try_new();
265 assert!(owner1.is_some());
266 let owner2 = TLCellOwner::<Marker>::try_new();
267 assert!(owner2.is_none());
268 }
269
270 #[test]
271 fn tlcell() {
272 struct Marker;
273 type ACellOwner = TLCellOwner<Marker>;
274 type ACell<T> = TLCell<Marker, T>;
275 let mut owner = ACellOwner::new();
276 let c1 = ACell::new(100u32);
277 let c2 = owner.cell(200u32);
278 (*owner.rw(&c1)) += 1;
279 (*owner.rw(&c2)) += 2;
280 let c1ref = owner.ro(&c1);
281 let c2ref = owner.ro(&c2);
282 let total = *c1ref + *c2ref;
283 assert_eq!(total, 303);
284 }
285
286 #[test]
287 fn tlcell_threads() {
288 struct Marker;
289 type ACellOwner = TLCellOwner<Marker>;
290 let mut _owner1 = ACellOwner::new();
291 std::thread::spawn(|| {
292 let mut _owner2 = ACellOwner::new();
293 })
294 .join()
295 .unwrap();
296 }
297
298 #[test]
299 fn tlcell_get_mut() {
300 struct Marker;
301 type ACellOwner = TLCellOwner<Marker>;
302 type ACell<T> = TLCell<Marker, T>;
303 let owner = ACellOwner::new();
304 let mut cell = ACell::new(100u32);
305 let mut_ref = cell.get_mut();
306 *mut_ref = 50;
307 let cell_ref = owner.ro(&cell);
308 assert_eq!(*cell_ref, 50);
309 }
310
311 #[test]
312 fn tlcell_into_inner() {
313 struct Marker;
314 type ACell<T> = TLCell<Marker, T>;
315 let cell = ACell::new(100u32);
316 assert_eq!(cell.into_inner(), 100);
317 }
318
319 #[test]
320 fn tlcell_unsized() {
321 struct Marker;
322 type ACellOwner = TLCellOwner<Marker>;
323 type ACell<T> = TLCell<Marker, T>;
324 let mut owner = ACellOwner::new();
325 struct Squares(u32);
326 struct Integers(u64);
327 trait Series {
328 fn step(&mut self);
329 fn value(&self) -> u64;
330 }
331 impl Series for Squares {
332 fn step(&mut self) {
333 self.0 += 1;
334 }
335 fn value(&self) -> u64 {
336 (self.0 as u64) * (self.0 as u64)
337 }
338 }
339 impl Series for Integers {
340 fn step(&mut self) {
341 self.0 += 1;
342 }
343 fn value(&self) -> u64 {
344 self.0
345 }
346 }
347 fn series(init: u32, is_squares: bool) -> Box<ACell<dyn Series>> {
348 if is_squares {
349 Box::new(ACell::new(Squares(init)))
350 } else {
351 Box::new(ACell::new(Integers(init as u64)))
352 }
353 }
354
355 let own = &mut owner;
356 let cell1 = series(4, false);
357 let cell2 = series(7, true);
358 let cell3 = series(3, true);
359 assert_eq!(cell1.ro(own).value(), 4);
360 cell1.rw(own).step();
361 assert_eq!(cell1.ro(own).value(), 5);
362 assert_eq!(own.ro(&cell2).value(), 49);
363 own.rw(&cell2).step();
364 assert_eq!(own.ro(&cell2).value(), 64);
365 let (r1, r2, r3) = own.rw3(&cell1, &cell2, &cell3);
366 r1.step();
367 r2.step();
368 r3.step();
369 assert_eq!(cell1.ro(own).value(), 6);
370 assert_eq!(cell2.ro(own).value(), 81);
371 assert_eq!(cell3.ro(own).value(), 16);
372 let (r1, r2) = own.rw2(&cell1, &cell2);
373 r1.step();
374 r2.step();
375 assert_eq!(cell1.ro(own).value(), 7);
376 assert_eq!(cell2.ro(own).value(), 100);
377 }
378}