Skip to main content

shipyard/
public_transport.rs

1use alloc::boxed::Box;
2use core::cell::UnsafeCell;
3use core::ops::{Deref, DerefMut};
4
5pub(crate) enum RwLock<T> {
6    Custom {
7        lock: Box<dyn ShipyardRwLock + Send + Sync>,
8        value: UnsafeCell<T>,
9    },
10    #[cfg(feature = "std")]
11    Std { lock: std::sync::RwLock<T> },
12}
13
14pub(crate) enum ReadGuard<'a, T> {
15    Custom {
16        lock: &'a dyn ShipyardRwLock,
17        value: &'a T,
18        marker: core::marker::PhantomData<(&'a T, lock_api::GuardNoSend)>,
19    },
20    #[cfg(feature = "std")]
21    Std {
22        guard: std::sync::RwLockReadGuard<'a, T>,
23    },
24}
25
26impl<'a, T> Deref for ReadGuard<'a, T> {
27    type Target = T;
28
29    fn deref(&self) -> &Self::Target {
30        match self {
31            Self::Custom { value, .. } => value,
32            #[cfg(feature = "std")]
33            Self::Std { guard } => guard,
34        }
35    }
36}
37
38impl<T> Drop for ReadGuard<'_, T> {
39    fn drop(&mut self) {
40        match self {
41            Self::Custom { lock, .. } => unsafe {
42                lock.unlock_shared();
43            },
44            #[cfg(feature = "std")]
45            Self::Std { .. } => {}
46        }
47    }
48}
49
50pub(crate) enum WriteGuard<'a, T> {
51    Custom {
52        lock: &'a dyn ShipyardRwLock,
53        value: &'a mut T,
54        marker: core::marker::PhantomData<(&'a mut T, lock_api::GuardNoSend)>,
55    },
56    #[cfg(feature = "std")]
57    Std {
58        guard: std::sync::RwLockWriteGuard<'a, T>,
59    },
60}
61
62impl<'a, T> Deref for WriteGuard<'a, T> {
63    type Target = T;
64
65    fn deref(&self) -> &Self::Target {
66        match self {
67            Self::Custom { value, .. } => value,
68            #[cfg(feature = "std")]
69            Self::Std { guard } => guard,
70        }
71    }
72}
73
74impl<'a, T> DerefMut for WriteGuard<'a, T> {
75    fn deref_mut(&mut self) -> &mut Self::Target {
76        match self {
77            Self::Custom { value, .. } => value,
78            #[cfg(feature = "std")]
79            Self::Std { guard } => guard,
80        }
81    }
82}
83
84impl<T> Drop for WriteGuard<'_, T> {
85    fn drop(&mut self) {
86        match self {
87            Self::Custom { lock, .. } => unsafe {
88                lock.unlock_exclusive();
89            },
90            #[cfg(feature = "std")]
91            Self::Std { .. } => {}
92        }
93    }
94}
95
96impl<T> RwLock<T> {
97    pub(crate) fn new_custom(lock: Box<dyn ShipyardRwLock + Send + Sync>, value: T) -> Self {
98        RwLock::Custom {
99            lock,
100            value: UnsafeCell::new(value),
101        }
102    }
103    #[cfg(feature = "std")]
104    pub(crate) fn new_std(value: T) -> Self {
105        RwLock::Std {
106            lock: std::sync::RwLock::new(value),
107        }
108    }
109    pub(crate) fn read(&self) -> ReadGuard<'_, T> {
110        match self {
111            RwLock::Custom { lock, value } => {
112                lock.lock_shared();
113
114                ReadGuard::Custom {
115                    lock: &**lock,
116                    value: unsafe { &*value.get() },
117                    marker: core::marker::PhantomData,
118                }
119            }
120            #[cfg(feature = "std")]
121            RwLock::Std { lock } => ReadGuard::Std {
122                guard: lock.read().unwrap(),
123            },
124        }
125    }
126    pub(crate) fn write(&self) -> WriteGuard<'_, T> {
127        match self {
128            RwLock::Custom { lock, value } => {
129                lock.lock_exclusive();
130
131                WriteGuard::Custom {
132                    lock: &**lock,
133                    value: unsafe { &mut *value.get() },
134                    marker: core::marker::PhantomData,
135                }
136            }
137            #[cfg(feature = "std")]
138            RwLock::Std { lock } => WriteGuard::Std {
139                guard: lock.write().unwrap(),
140            },
141        }
142    }
143    pub(crate) fn get_mut(&mut self) -> &mut T {
144        match self {
145            RwLock::Custom { value, .. } => value.get_mut(),
146            #[cfg(feature = "std")]
147            RwLock::Std { lock } => lock.get_mut().unwrap(),
148        }
149    }
150}
151
152pub trait ShipyardRwLock {
153    #[allow(clippy::new_ret_no_self)]
154    fn new() -> Box<dyn ShipyardRwLock + Send + Sync>
155    where
156        Self: Sized;
157    fn lock_shared(&self);
158    unsafe fn unlock_shared(&self);
159    fn lock_exclusive(&self);
160    unsafe fn unlock_exclusive(&self);
161}
162
163impl<T> ShipyardRwLock for T
164where
165    T: 'static + lock_api::RawRwLock + Send + Sync,
166{
167    fn new() -> Box<dyn ShipyardRwLock + Send + Sync>
168    where
169        Self: Sized,
170    {
171        Box::new(T::INIT)
172    }
173    fn lock_shared(&self) {
174        lock_api::RawRwLock::lock_shared(self)
175    }
176
177    unsafe fn unlock_shared(&self) {
178        lock_api::RawRwLock::unlock_shared(self)
179    }
180
181    fn lock_exclusive(&self) {
182        lock_api::RawRwLock::lock_exclusive(self)
183    }
184
185    unsafe fn unlock_exclusive(&self) {
186        lock_api::RawRwLock::unlock_exclusive(self)
187    }
188}