rx_rust/utils/
types.rs

1use std::marker::PhantomData;
2
3/// Using `PhantomData<fn(T) -> T>` instead of `PhantomData<T>` to make MarkerType to be `NecessarySendSync` when T is not `NecessarySendSync`.
4/// For more detail: <https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns>
5/// But the lifetime of MarkerType is affected by T. Which means T and MarkerType have the same lifetime.
6/// TODO: find a better solution, so we can remove some restriction like `T: 'static` in some cases.
7/// For more detail: <https://users.rust-lang.org/t/getting-phantomdata-to-have-a-static-lifetime/38505>
8pub type MarkerType<T> = PhantomData<fn(T) -> T>;
9
10pub trait MutableHelper<T> {
11    fn lock_mut<R>(&self, callback: impl FnOnce(MutGuard<'_, T>) -> R) -> R;
12    fn lock_ref<R>(&self, callback: impl FnOnce(RefGuard<'_, T>) -> R) -> R;
13}
14
15cfg_if::cfg_if! {
16    if #[cfg(feature = "single-threaded")] {
17        use std::{
18            cell::{Ref, RefCell, RefMut},
19            rc::Rc,
20        };
21        pub type Shared<T> = Rc<T>;
22        pub type Mutable<T> = RefCell<T>;
23        pub type MutGuard<'a, T> = RefMut<'a, T>;
24        pub type RefGuard<'a, T> = Ref<'a, T>;
25        impl<T> MutableHelper<T> for RefCell<T> {
26            fn lock_mut<R>(&self, callback: impl FnOnce(MutGuard<'_, T>) -> R) ->R {
27                callback(self.borrow_mut())
28            }
29            fn lock_ref<R>(&self, callback: impl FnOnce(RefGuard<'_, T>) ->R) ->R {
30                callback(self.borrow())
31            }
32        }
33        pub trait NecessarySendSync {}
34        impl<T> NecessarySendSync for T {}
35    } else {
36        use std::sync::{Arc, Mutex, MutexGuard};
37        use std::ops::Deref;
38        use educe::Educe;
39
40        pub type Shared<T> = Arc<T>;
41        pub type Mutable<T> = Mutex<T>;
42
43        #[derive(Educe)]
44        #[educe(Debug)]
45        pub struct ReadOnlyMutexGuard<'a, T: ?Sized + 'a>(MutexGuard<'a, T>);
46        impl<'a, T> ReadOnlyMutexGuard<'a, T> {
47            pub fn new(guard: MutexGuard<'a, T>) -> Self {
48                Self(guard)
49            }
50        }
51        impl<T: ?Sized> Deref for ReadOnlyMutexGuard<'_, T> {
52            type Target = T;
53            fn deref(&self) -> &T {
54                &self.0
55            }
56        }
57        pub type MutGuard<'a, T> = MutexGuard<'a, T>;
58        pub type RefGuard<'a, T> = ReadOnlyMutexGuard<'a, T>;
59        impl<T> MutableHelper<T> for Mutex<T> {
60            fn lock_mut<R>(&self, callback: impl FnOnce(MutGuard<'_, T>) -> R) ->R {
61                callback(self.lock().unwrap())
62            }
63            fn lock_ref<R>(&self, callback: impl FnOnce(RefGuard<'_, T>) ->R) ->R {
64                callback(ReadOnlyMutexGuard(self.lock().unwrap()))
65            }
66        }
67        pub trait NecessarySendSync: Send + Sync {}
68        impl<T> NecessarySendSync for T where T: Send + Sync {}
69    }
70}