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