]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/sgx/waitqueue/spin_mutex.rs
7f1a671bab4eb73bccb31da09d1f3e4558c94ea8
[rust.git] / library / std / src / sys / sgx / waitqueue / spin_mutex.rs
1 #[cfg(test)]
2 mod tests;
3
4 use crate::cell::UnsafeCell;
5 use crate::hint;
6 use crate::ops::{Deref, DerefMut};
7 use crate::sync::atomic::{AtomicBool, Ordering};
8
9 #[derive(Default)]
10 pub struct SpinMutex<T> {
11     value: UnsafeCell<T>,
12     lock: AtomicBool,
13 }
14
15 unsafe impl<T: Send> Send for SpinMutex<T> {}
16 unsafe impl<T: Send> Sync for SpinMutex<T> {}
17
18 pub struct SpinMutexGuard<'a, T: 'a> {
19     mutex: &'a SpinMutex<T>,
20 }
21
22 impl<'a, T> !Send for SpinMutexGuard<'a, T> {}
23 unsafe impl<'a, T: Sync> Sync for SpinMutexGuard<'a, T> {}
24
25 impl<T> SpinMutex<T> {
26     pub const fn new(value: T) -> Self {
27         SpinMutex { value: UnsafeCell::new(value), lock: AtomicBool::new(false) }
28     }
29
30     #[inline(always)]
31     pub fn lock(&self) -> SpinMutexGuard<'_, T> {
32         loop {
33             match self.try_lock() {
34                 None => {
35                     while self.lock.load(Ordering::Relaxed) {
36                         hint::spin_loop()
37                     }
38                 }
39                 Some(guard) => return guard,
40             }
41         }
42     }
43
44     #[inline(always)]
45     pub fn try_lock(&self) -> Option<SpinMutexGuard<'_, T>> {
46         if self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Acquire).is_ok() {
47             Some(SpinMutexGuard { mutex: self })
48         } else {
49             None
50         }
51     }
52 }
53
54 /// Lock the Mutex or return false.
55 pub macro try_lock_or_false($e:expr) {
56     if let Some(v) = $e.try_lock() { v } else { return false }
57 }
58
59 impl<'a, T> Deref for SpinMutexGuard<'a, T> {
60     type Target = T;
61
62     fn deref(&self) -> &T {
63         unsafe { &*self.mutex.value.get() }
64     }
65 }
66
67 impl<'a, T> DerefMut for SpinMutexGuard<'a, T> {
68     fn deref_mut(&mut self) -> &mut T {
69         unsafe { &mut *self.mutex.value.get() }
70     }
71 }
72
73 impl<'a, T> Drop for SpinMutexGuard<'a, T> {
74     fn drop(&mut self) {
75         self.mutex.lock.store(false, Ordering::Release)
76     }
77 }