1use core::{
2 cell::UnsafeCell,
3 fmt::{self, Debug, Formatter},
4 hint::spin_loop,
5 mem::{self, transmute, ManuallyDrop, MaybeUninit},
6 ops::Deref,
7 ptr::drop_in_place,
8 sync::atomic::{AtomicU8, Ordering},
9};
10
11#[cfg(feature = "alloc")]
12use alloc::sync::Arc;
13
14#[cfg(feature = "alloc")]
15use super::arc::{MutexGuardArc, OptionGuardArc};
16
17use super::error::OptionLockError;
18
19use super::mutex::MutexGuard;
20
21#[repr(transparent)]
22pub(crate) struct State(AtomicU8);
23
24impl State {
25 pub const FREE: u8 = 1 << 0;
26 pub const SOME: u8 = 1 << 1;
27 pub const AVAILABLE: u8 = Self::FREE | Self::SOME;
28
29 pub const fn new(value: u8) -> Self {
30 Self(AtomicU8::new(value))
31 }
32
33 #[inline]
34 pub fn is_some_mut(&mut self) -> bool {
35 *self.0.get_mut() & State::SOME != 0
36 }
37
38 #[inline]
39 pub fn value(&self) -> u8 {
40 self.0.load(Ordering::Relaxed)
41 }
42}
43
44impl Deref for State {
45 type Target = AtomicU8;
46
47 #[inline]
48 fn deref(&self) -> &AtomicU8 {
49 &self.0
50 }
51}
52
53impl Debug for State {
54 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
55 f.write_str(match self.0.load(Ordering::Relaxed) {
56 Self::FREE => "None",
57 Self::AVAILABLE => "Some",
58 _ => "Locked",
59 })
60 }
61}
62
63impl PartialEq<u8> for State {
64 #[inline]
65 fn eq(&self, other: &u8) -> bool {
66 self.0.load(Ordering::Relaxed) == *other
67 }
68}
69
70pub struct OptionLock<T> {
72 data: UnsafeCell<MaybeUninit<T>>,
73 pub(crate) state: State,
74}
75
76impl<T> Default for OptionLock<T> {
77 fn default() -> Self {
78 Self::empty()
79 }
80}
81
82unsafe impl<T: Send> Send for OptionLock<T> {}
83unsafe impl<T: Send> Sync for OptionLock<T> {}
84
85impl<T> OptionLock<T> {
86 pub const fn empty() -> Self {
88 Self {
89 data: UnsafeCell::new(MaybeUninit::uninit()),
90 state: State::new(State::FREE),
91 }
92 }
93
94 pub const fn new(value: T) -> Self {
96 Self {
97 data: UnsafeCell::new(MaybeUninit::new(value)),
98 state: State::new(State::AVAILABLE),
99 }
100 }
101
102 #[inline]
103 pub(crate) unsafe fn as_ptr(&self) -> *const T {
104 (&*self.data.get()).as_ptr()
105 }
106
107 #[inline]
108 pub(crate) unsafe fn as_mut_ptr(&self) -> *mut T {
109 (&mut *self.data.get()).as_mut_ptr()
110 }
111
112 #[inline]
114 pub fn is_none_unlocked(&self) -> bool {
115 self.state == State::FREE
116 }
117
118 #[inline]
120 pub fn is_some_unlocked(&self) -> bool {
121 self.state == State::AVAILABLE
122 }
123
124 #[inline]
125 pub(crate) fn is_some(&self) -> bool {
126 self.state.value() & State::SOME != 0
127 }
128
129 #[inline]
131 pub fn is_locked(&self) -> bool {
132 self.state.value() & State::FREE == 0
133 }
134
135 pub fn get_mut(&mut self) -> Option<&mut T> {
137 if self.is_some() {
138 Some(unsafe { &mut *self.as_mut_ptr() })
139 } else {
140 None
141 }
142 }
143
144 pub fn into_inner(mut self) -> Option<T> {
146 if self.state.is_some_mut() {
147 let slf = ManuallyDrop::new(self);
148 Some(unsafe { slf.as_mut_ptr().read() })
149 } else {
150 None
151 }
152 }
153
154 pub fn spin_get(&self) -> MutexGuard<'_, T> {
156 loop {
157 if let Ok(guard) = self.try_get() {
158 return guard;
159 }
160 while !self.is_some_unlocked() {
161 spin_loop();
162 }
163 }
164 }
165
166 pub fn spin_lock(&self) -> OptionGuard<'_, T> {
168 loop {
169 if let Ok(guard) = self.try_lock() {
170 return guard;
171 }
172 while self.is_locked() {
173 spin_loop();
174 }
175 }
176 }
177
178 pub fn spin_lock_none(&self) -> OptionGuard<'_, T> {
180 loop {
181 if let Ok(guard) = self.try_lock_none() {
182 return guard;
183 }
184 while !self.is_none_unlocked() {
185 spin_loop();
186 }
187 }
188 }
189
190 pub fn spin_take(&self) -> T {
192 loop {
193 if let Ok(result) = self.try_take() {
194 return result;
195 }
196 while !self.is_some_unlocked() {
197 spin_loop();
198 }
199 }
200 }
201
202 pub fn try_get(&self) -> Result<MutexGuard<'_, T>, OptionLockError> {
207 match self.state.compare_exchange(
208 State::AVAILABLE,
209 State::SOME,
210 Ordering::AcqRel,
211 Ordering::Relaxed,
212 ) {
213 Ok(_) => Ok(MutexGuard::new(OptionGuard::new(self, true))),
214 Err(State::FREE) => Err(OptionLockError::FillState),
215 Err(_) => Err(OptionLockError::Unavailable),
216 }
217 }
218
219 #[cfg(feature = "alloc")]
220 pub fn try_get_arc(self: &Arc<Self>) -> Result<MutexGuardArc<T>, OptionLockError> {
225 self.try_get()
226 .map(|guard| MutexGuardArc::new(unsafe { transmute(self.clone()) }, guard))
227 }
228
229 pub fn try_fill(&self, value: T) -> Result<(), T> {
231 match self
232 .state
233 .compare_exchange(State::FREE, 0, Ordering::AcqRel, Ordering::Relaxed)
234 {
235 Ok(_) => {
236 OptionGuard::new(self, false).replace(value);
237 Ok(())
238 }
239 Err(_) => Err(value),
240 }
241 }
242
243 pub fn try_fill_with(&self, f: impl FnOnce() -> T) -> Result<(), OptionLockError> {
247 self.try_lock_none()?.replace(f());
248 Ok(())
249 }
250
251 pub fn try_lock(&self) -> Result<OptionGuard<'_, T>, OptionLockError> {
256 let state = self.state.fetch_and(!State::FREE, Ordering::Release);
257 if state & State::FREE != 0 {
258 Ok(OptionGuard::new(self, state & State::SOME != 0))
259 } else {
260 Err(OptionLockError::Unavailable)
261 }
262 }
263
264 #[cfg(feature = "alloc")]
265 pub fn try_lock_arc(self: &Arc<Self>) -> Result<OptionGuardArc<T>, OptionLockError> {
270 self.try_lock()
271 .map(|guard| OptionGuardArc::new(self.clone(), guard))
272 }
273
274 pub fn try_lock_none(&self) -> Result<OptionGuard<'_, T>, OptionLockError> {
276 match self
277 .state
278 .compare_exchange(State::FREE, 0, Ordering::AcqRel, Ordering::Relaxed)
279 {
280 Ok(_) => return Ok(OptionGuard::new(self, false)),
281 Err(State::AVAILABLE) => Err(OptionLockError::FillState),
282 Err(_) => Err(OptionLockError::Unavailable),
283 }
284 }
285
286 #[cfg(feature = "alloc")]
287 pub fn try_lock_empty_arc(self: &Arc<Self>) -> Result<OptionGuardArc<T>, OptionLockError> {
289 self.try_lock_none()
290 .map(|guard| OptionGuardArc::new(self.clone(), guard))
291 }
292
293 #[inline]
295 pub fn try_take(&self) -> Result<T, OptionLockError> {
296 self.try_get().map(MutexGuard::extract)
297 }
298
299 pub fn replace(&mut self, value: T) -> Option<T> {
301 let result = if self.is_some() {
302 Some(unsafe { self.as_mut_ptr().read() })
303 } else {
304 self.state.fetch_or(State::SOME, Ordering::Relaxed);
305 None
306 };
307 unsafe { self.as_mut_ptr().write(value) };
308 result
309 }
310
311 pub fn take(&mut self) -> Option<T> {
313 if self.is_some() {
314 self.state.fetch_and(!State::SOME, Ordering::Relaxed);
315 Some(unsafe { self.as_mut_ptr().read() })
316 } else {
317 None
318 }
319 }
320}
321
322impl<T: Clone> OptionLock<T> {
323 #[inline]
325 pub fn try_clone(&self) -> Result<T, OptionLockError> {
326 self.try_get().map(|g| (*g).clone())
327 }
328}
329
330impl<T: Copy> OptionLock<T> {
331 #[inline]
333 pub fn try_copy(&self) -> Result<T, OptionLockError> {
334 self.try_get().map(|g| *g)
335 }
336}
337
338impl<T> Drop for OptionLock<T> {
339 fn drop(&mut self) {
340 if self.state.is_some_mut() {
341 unsafe {
342 drop_in_place(self.as_mut_ptr());
343 }
344 }
345 }
346}
347
348impl<T> From<T> for OptionLock<T> {
349 fn from(data: T) -> Self {
350 Self::new(data)
351 }
352}
353
354impl<T> From<Option<T>> for OptionLock<T> {
355 fn from(data: Option<T>) -> Self {
356 if let Some(data) = data {
357 Self::new(data)
358 } else {
359 Self::empty()
360 }
361 }
362}
363
364impl<T> Into<Option<T>> for OptionLock<T> {
365 fn into(mut self) -> Option<T> {
366 self.take()
367 }
368}
369
370impl<T> Debug for OptionLock<T> {
371 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
372 write!(f, "OptionLock({:?})", &self.state)
373 }
374}
375
376pub struct OptionGuard<'a, T> {
378 lock: &'a OptionLock<T>,
379 is_some: bool,
380}
381
382impl<'a, T> OptionGuard<'a, T> {
383 #[inline]
384 pub(crate) fn new(lock: &'a OptionLock<T>, is_some: bool) -> Self {
385 Self { lock, is_some }
386 }
387}
388
389impl<T> OptionGuard<'_, T> {
390 pub fn as_ref(&self) -> Option<&T> {
392 if self.is_some {
393 Some(unsafe { &*self.lock.as_ptr() })
394 } else {
395 None
396 }
397 }
398
399 pub fn as_mut(&mut self) -> Option<&mut T> {
401 if self.is_some {
402 Some(unsafe { &mut *self.lock.as_mut_ptr() })
403 } else {
404 None
405 }
406 }
407
408 #[inline]
410 pub fn is_none(&self) -> bool {
411 !self.is_some
412 }
413
414 #[inline]
416 pub fn is_some(&self) -> bool {
417 self.is_some
418 }
419
420 pub fn replace(&mut self, value: T) -> Option<T> {
422 if self.is_some {
423 Some(mem::replace(unsafe { &mut *self.lock.as_mut_ptr() }, value))
424 } else {
425 self.is_some = true;
426 unsafe {
427 self.lock.as_mut_ptr().write(value);
428 }
429 None
430 }
431 }
432
433 pub fn take(&mut self) -> Option<T> {
435 if self.is_some {
436 self.is_some = false;
437 Some(unsafe { self.lock.as_ptr().read() })
438 } else {
439 None
440 }
441 }
442}
443
444impl<T: Debug> Debug for OptionGuard<'_, T> {
445 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
446 f.debug_tuple("OptionGuard").field(&self.as_ref()).finish()
447 }
448}
449
450impl<'a, T> Drop for OptionGuard<'a, T> {
451 fn drop(&mut self) {
452 self.lock.state.store(
453 if self.is_some {
454 State::AVAILABLE
455 } else {
456 State::FREE
457 },
458 Ordering::Release,
459 );
460 }
461}
462
463unsafe impl<T: Send> Send for OptionGuard<'_, T> {}
464unsafe impl<T: Sync> Sync for OptionGuard<'_, T> {}