shipyard/
public_transport.rs1use 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}