1#[cfg(any(feature = "std", feature = "exclusion-set"))]
2use core::any::TypeId;
3use core::cell::UnsafeCell;
4use core::marker::PhantomData;
5#[cfg(all(feature = "std", not(feature = "exclusion-set")))]
6use once_cell::sync::Lazy;
7#[cfg(all(feature = "std", not(feature = "exclusion-set")))]
8use std::{
9 collections::HashSet,
10 sync::{Condvar, Mutex},
11};
12
13use super::Invariant;
14
15#[cfg(all(feature = "std", not(feature = "exclusion-set")))]
16static SINGLETON_CHECK: Lazy<Mutex<HashSet<TypeId>>> = Lazy::new(|| Mutex::new(HashSet::new()));
17#[cfg(all(feature = "std", not(feature = "exclusion-set")))]
18static SINGLETON_CHECK_CONDVAR: Lazy<Condvar> = Lazy::new(Condvar::new);
19#[cfg(feature = "exclusion-set")]
20static SINGLETON_CHECK_SET: exclusion_set::Set<TypeId> = exclusion_set::Set::new();
21
22pub struct TCellOwner<Q: 'static> {
27 typ: PhantomData<Invariant<Q>>,
29}
30
31impl<Q: 'static> Drop for TCellOwner<Q> {
32 #[cfg(all(feature = "std", not(feature = "exclusion-set")))]
33 fn drop(&mut self) {
34 SINGLETON_CHECK.lock().unwrap().remove(&TypeId::of::<Q>());
37
38 SINGLETON_CHECK_CONDVAR.notify_all();
41 }
42
43 #[cfg(feature = "exclusion-set")]
44 fn drop(&mut self) {
45 unsafe {
50 SINGLETON_CHECK_SET.remove(&TypeId::of::<Q>());
51 }
52 }
53
54 #[cfg(not(any(feature = "std", feature = "exclusion-set")))]
55 fn drop(&mut self) {
56 unreachable!()
59 }
60}
61
62#[cfg(any(feature = "std", feature = "exclusion-set"))]
63#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "exclusion-set"))))]
64impl<Q: 'static> Default for TCellOwner<Q> {
65 fn default() -> Self {
66 TCellOwner::new()
67 }
68}
69
70impl<Q: 'static> TCellOwner<Q> {
71 #[cfg_attr(feature = "std", doc = "[`TCellOwner::wait_for_new`]")]
82 #[cfg_attr(not(feature = "std"), doc = "`TCellOwner::wait_for_new`")]
83 #[cfg(any(feature = "std", feature = "exclusion-set"))]
85 #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "exclusion-set"))))]
86 pub fn new() -> Self {
87 if let Some(owner) = TCellOwner::try_new() {
88 owner
89 } else {
90 panic!("Illegal to create two TCellOwner instances with the same marker type parameter")
91 }
92 }
93
94 #[cfg(all(feature = "std", not(feature = "exclusion-set")))]
98 pub fn try_new() -> Option<Self> {
99 if SINGLETON_CHECK.lock().unwrap().insert(TypeId::of::<Q>()) {
100 Some(Self { typ: PhantomData })
101 } else {
102 None
103 }
104 }
105
106 #[cfg(feature = "exclusion-set")]
110 #[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "exclusion-set"))))]
111 pub fn try_new() -> Option<Self> {
112 if SINGLETON_CHECK_SET.try_insert(TypeId::of::<Q>()) {
113 Some(Self { typ: PhantomData })
114 } else {
115 None
116 }
117 }
118
119 #[cfg(all(feature = "std", not(feature = "exclusion-set")))]
132 pub fn wait_for_new() -> Self {
133 let hashset_guard = SINGLETON_CHECK.lock().unwrap();
135
136 let mut hashset_guard = SINGLETON_CHECK_CONDVAR
140 .wait_while(hashset_guard, |hashset| {
141 hashset.contains(&TypeId::of::<Q>())
142 })
143 .unwrap();
144
145 let inserted = hashset_guard.insert(TypeId::of::<Q>());
149 assert!(inserted);
150 Self { typ: PhantomData }
151 }
152
153 #[cfg(all(feature = "std", feature = "exclusion-set"))]
166 #[cfg_attr(
167 docsrs,
168 doc(cfg(any(feature = "std", all(feature = "exclusion-set", feature = "std"))))
169 )]
170 pub fn wait_for_new() -> Self {
171 SINGLETON_CHECK_SET.wait_to_insert(TypeId::of::<Q>());
172 Self { typ: PhantomData }
173 }
174
175 pub fn cell<T>(&self, value: T) -> TCell<Q, T> {
180 TCell::<Q, T>::new(value)
181 }
182
183 #[inline]
187 pub fn ro<'a, T: ?Sized>(&'a self, tc: &'a TCell<Q, T>) -> &'a T {
188 unsafe { &*tc.value.get() }
189 }
190
191 #[inline]
196 pub fn rw<'a, T: ?Sized>(&'a mut self, tc: &'a TCell<Q, T>) -> &'a mut T {
197 unsafe { &mut *tc.value.get() }
198 }
199
200 #[inline]
203 pub fn rw2<'a, T: ?Sized, U: ?Sized>(
204 &'a mut self,
205 tc1: &'a TCell<Q, T>,
206 tc2: &'a TCell<Q, U>,
207 ) -> (&'a mut T, &'a mut U) {
208 assert!(
209 tc1 as *const _ as *const () as usize != tc2 as *const _ as *const () as usize,
210 "Illegal to borrow same TCell twice with rw2()"
211 );
212 unsafe { (&mut *tc1.value.get(), &mut *tc2.value.get()) }
213 }
214
215 #[inline]
218 pub fn rw3<'a, T: ?Sized, U: ?Sized, V: ?Sized>(
219 &'a mut self,
220 tc1: &'a TCell<Q, T>,
221 tc2: &'a TCell<Q, U>,
222 tc3: &'a TCell<Q, V>,
223 ) -> (&'a mut T, &'a mut U, &'a mut V) {
224 assert!(
225 (tc1 as *const _ as *const () as usize != tc2 as *const _ as *const () as usize)
226 && (tc2 as *const _ as *const () as usize != tc3 as *const _ as *const () as usize)
227 && (tc3 as *const _ as *const () as usize != tc1 as *const _ as *const () as usize),
228 "Illegal to borrow same TCell twice with rw3()"
229 );
230 unsafe {
231 (
232 &mut *tc1.value.get(),
233 &mut *tc2.value.get(),
234 &mut *tc3.value.get(),
235 )
236 }
237 }
238}
239
240#[repr(transparent)]
250pub struct TCell<Q, T: ?Sized> {
251 owner: PhantomData<Invariant<Q>>,
253
254 value: UnsafeCell<T>,
261}
262
263impl<Q, T> TCell<Q, T> {
264 #[inline]
267 pub const fn new(value: T) -> TCell<Q, T> {
268 TCell {
269 owner: PhantomData,
270 value: UnsafeCell::new(value),
271 }
272 }
273
274 #[inline]
279 pub fn into_inner(self) -> T {
280 self.value.into_inner()
281 }
282}
283
284impl<Q, T: ?Sized> TCell<Q, T> {
285 #[inline]
289 pub fn ro<'a>(&'a self, owner: &'a TCellOwner<Q>) -> &'a T {
290 owner.ro(self)
291 }
292
293 #[inline]
300 pub fn rw<'a>(&'a self, owner: &'a mut TCellOwner<Q>) -> &'a mut T {
301 owner.rw(self)
302 }
303
304 #[inline]
316 pub fn get_mut(&mut self) -> &mut T {
317 self.value.get_mut()
318 }
319}
320
321impl<Q: 'static, T: Default + ?Sized> Default for TCell<Q, T> {
322 fn default() -> Self {
323 TCell::new(T::default())
324 }
325}
326
327unsafe impl<Q, T: Send + Sync + ?Sized> Sync for TCell<Q, T> {}
343
344#[cfg(all(test, any(feature = "std", feature = "exclusion-set")))]
345mod tests {
346 use super::{TCell, TCellOwner};
347 #[test]
348 #[should_panic]
349 fn tcell_singleton_1() {
350 struct Marker;
351 let _owner1 = TCellOwner::<Marker>::new();
352 let _owner2 = TCellOwner::<Marker>::new(); }
354
355 #[test]
356 fn tcell_singleton_2() {
357 struct Marker;
358 let owner1 = TCellOwner::<Marker>::new();
359 drop(owner1);
360 let _owner2 = TCellOwner::<Marker>::new();
361 }
362
363 #[test]
364 fn tcell_singleton_3() {
365 struct Marker1;
366 struct Marker2;
367 let _owner1 = TCellOwner::<Marker1>::new();
368 let _owner2 = TCellOwner::<Marker2>::new();
369 }
370
371 #[test]
372 fn tcell_singleton_try_new() {
373 struct Marker;
374 let owner1 = TCellOwner::<Marker>::try_new();
375 assert!(owner1.is_some());
376 let owner2 = TCellOwner::<Marker>::try_new();
377 assert!(owner2.is_none());
378 }
379
380 #[test]
381 fn tcell() {
382 struct Marker;
383 type ACellOwner = TCellOwner<Marker>;
384 type ACell<T> = TCell<Marker, T>;
385 let mut owner = ACellOwner::new();
386 let c1 = ACell::new(100u32);
387 let c2 = owner.cell(200u32);
388 (*owner.rw(&c1)) += 1;
389 (*owner.rw(&c2)) += 2;
390 let c1ref = owner.ro(&c1);
391 let c2ref = owner.ro(&c2);
392 let total = *c1ref + *c2ref;
393 assert_eq!(total, 303);
394 }
395
396 #[test]
397 #[should_panic]
398 fn tcell_threads() {
399 struct Marker;
400 type ACellOwner = TCellOwner<Marker>;
401 let (tx, rx) = std::sync::mpsc::sync_channel(0);
404 std::thread::spawn(move || {
405 let mut _owner = ACellOwner::new();
406 tx.send(()).unwrap();
407 let _ = tx.send(());
410 });
411 rx.recv().unwrap();
412 let mut _owner = ACellOwner::new(); let _ = rx.recv();
414 }
415
416 #[cfg(feature = "std")]
417 #[test]
418 fn tcell_wait_for_new_in_100_threads() {
419 use rand::Rng;
420 use std::sync::Arc;
421 struct Marker;
422 type ACellOwner = TCellOwner<Marker>;
423 type ACell = TCell<Marker, i32>;
424 let cell_arc = Arc::new(ACell::new(0));
425 let mut handles = vec![];
426 for _ in 0..100 {
427 let cell_arc_clone = cell_arc.clone();
428 let handle = std::thread::spawn(move || {
429 let mut rng = rand::thread_rng();
431 std::thread::sleep(std::time::Duration::from_millis(rng.gen_range(0..10)));
432 let mut owner = ACellOwner::wait_for_new();
434 let current_cell_val = *owner.ro(&*cell_arc_clone);
436 std::thread::sleep(std::time::Duration::from_millis(rng.gen_range(0..10)));
438 *owner.rw(&*cell_arc_clone) = current_cell_val + 1;
442 });
443 handles.push(handle);
444 }
445 for handle in handles {
446 assert!(handle.join().is_ok());
447 }
448 let owner = ACellOwner::wait_for_new();
449 assert_eq!(*owner.ro(&*cell_arc), 100);
450 }
451
452 #[cfg(feature = "std")]
453 #[test]
454 fn tcell_wait_for_new_timeout() {
455 fn assert_time_out<F>(d: std::time::Duration, f: F)
456 where
457 F: FnOnce(),
458 F: Send + 'static,
459 {
460 let (done_tx, done_rx) = std::sync::mpsc::channel();
461 let _handle = std::thread::spawn(move || {
462 let val = f();
463 done_tx.send(()).unwrap();
464 val
465 });
466
467 assert!(
468 done_rx.recv_timeout(d).is_err(),
469 "ACellOwner::wait_for_new completed (but it shouldn't have)"
470 );
471 }
472
473 assert_time_out(std::time::Duration::from_millis(1000), || {
474 struct Marker;
475 type ACellOwner = TCellOwner<Marker>;
476
477 let _owner1 = ACellOwner::new();
478 let _owner2 = ACellOwner::wait_for_new();
479 });
480 }
481
482 #[test]
483 fn tcell_get_mut() {
484 struct Marker;
485 type ACellOwner = TCellOwner<Marker>;
486 type ACell<T> = TCell<Marker, T>;
487 let owner = ACellOwner::new();
488 let mut cell = ACell::new(100u32);
489 let mut_ref = cell.get_mut();
490 *mut_ref = 50;
491 let cell_ref = owner.ro(&cell);
492 assert_eq!(*cell_ref, 50);
493 }
494
495 #[test]
496 fn tcell_into_inner() {
497 struct Marker;
498 type ACell<T> = TCell<Marker, T>;
499 let cell = ACell::new(100u32);
500 assert_eq!(cell.into_inner(), 100);
501 }
502
503 #[test]
504 fn tcell_unsized() {
505 struct Marker;
506 type ACellOwner = TCellOwner<Marker>;
507 type ACell<T> = TCell<Marker, T>;
508 let mut owner = ACellOwner::new();
509 struct Squares(u32);
510 struct Integers(u64);
511 trait Series {
512 fn step(&mut self);
513 fn value(&self) -> u64;
514 }
515 impl Series for Squares {
516 fn step(&mut self) {
517 self.0 += 1;
518 }
519 fn value(&self) -> u64 {
520 (self.0 as u64) * (self.0 as u64)
521 }
522 }
523 impl Series for Integers {
524 fn step(&mut self) {
525 self.0 += 1;
526 }
527 fn value(&self) -> u64 {
528 self.0
529 }
530 }
531 fn series(init: u32, is_squares: bool) -> Box<ACell<dyn Series>> {
532 if is_squares {
533 Box::new(ACell::new(Squares(init)))
534 } else {
535 Box::new(ACell::new(Integers(init as u64)))
536 }
537 }
538
539 let own = &mut owner;
540 let cell1 = series(4, false);
541 let cell2 = series(7, true);
542 let cell3 = series(3, true);
543 assert_eq!(cell1.ro(own).value(), 4);
544 cell1.rw(own).step();
545 assert_eq!(cell1.ro(own).value(), 5);
546 assert_eq!(own.ro(&cell2).value(), 49);
547 own.rw(&cell2).step();
548 assert_eq!(own.ro(&cell2).value(), 64);
549 let (r1, r2, r3) = own.rw3(&cell1, &cell2, &cell3);
550 r1.step();
551 r2.step();
552 r3.step();
553 assert_eq!(cell1.ro(own).value(), 6);
554 assert_eq!(cell2.ro(own).value(), 81);
555 assert_eq!(cell3.ro(own).value(), 16);
556 let (r1, r2) = own.rw2(&cell1, &cell2);
557 r1.step();
558 r2.step();
559 assert_eq!(cell1.ro(own).value(), 7);
560 assert_eq!(cell2.ro(own).value(), 100);
561 }
562}