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 `NecessarySend + Sync` when T is not `NecessarySend + Sync`.
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 NecessarySend {}
34        impl<T> NecessarySend for T {}
35    } else {
36        use std::sync::{Arc, Mutex, MutexGuard};
37        use std::ops::Deref;
38        pub type Shared<T> = Arc<T>;
39        pub type Mutable<T> = Mutex<T>;
40        pub struct ReadOnlyMutexGuard<'a, T: ?Sized + 'a>(MutexGuard<'a, T>);
41        impl<'a, T> ReadOnlyMutexGuard<'a, T> {
42            pub fn new(guard: MutexGuard<'a, T>) -> Self {
43                Self(guard)
44            }
45        }
46        impl<T: ?Sized> Deref for ReadOnlyMutexGuard<'_, T> {
47            type Target = T;
48            fn deref(&self) -> &T {
49                &self.0
50            }
51        }
52        pub type MutGuard<'a, T> = MutexGuard<'a, T>;
53        pub type RefGuard<'a, T> = ReadOnlyMutexGuard<'a, T>;
54        impl<T> MutableHelper<T> for Mutex<T> {
55            fn lock_mut<R>(&self, callback: impl FnOnce(MutGuard<'_, T>) -> R) ->R {
56                callback(self.lock().unwrap())
57            }
58            fn lock_ref<R>(&self, callback: impl FnOnce(RefGuard<'_, T>) ->R) ->R {
59                callback(ReadOnlyMutexGuard(self.lock().unwrap()))
60            }
61        }
62        pub trait NecessarySend: Send {}
63        impl<T> NecessarySend for T where T: Send {}
64    }
65}