You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
68 lines
1.5 KiB
68 lines
1.5 KiB
use core::{cell::UnsafeCell, mem, sync::atomic::{AtomicBool, Ordering}}; |
|
|
|
pub struct SpinLock<T> { |
|
lock: AtomicBool, |
|
inner: UnsafeCell<Option<T>> |
|
} |
|
|
|
impl<T> SpinLock<T> { |
|
pub const fn new(inner: T) -> Self { |
|
Self { |
|
lock: AtomicBool::new(true), |
|
inner: UnsafeCell::new(Some(inner)) |
|
} |
|
} |
|
|
|
pub fn take(&self) -> T { |
|
loop { |
|
while self.lock.load(Ordering::Relaxed) == false {} |
|
if let Ok(_) = self.lock.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) |
|
{ |
|
break; |
|
} |
|
} |
|
|
|
if let Some(inner) = unsafe { &mut *self.inner.get() }.take() { |
|
inner |
|
} else { |
|
panic!() |
|
} |
|
} |
|
|
|
pub fn take_maybe(&self) -> Option<T> { |
|
if self.lock.load(Ordering::Relaxed) == false { |
|
if let Ok(_) = self.lock.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed) { |
|
unsafe { &mut *self.inner.get() }.take() |
|
} else { |
|
None |
|
} |
|
} else { |
|
None |
|
} |
|
} |
|
|
|
pub fn put(&self, inner: T) { |
|
loop { |
|
while self.lock.load(Ordering::Relaxed) == true {} |
|
if let Ok(_) = self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) |
|
{ |
|
break; |
|
} |
|
} |
|
|
|
unsafe { &mut *self.inner.get() }.insert(inner); |
|
} |
|
|
|
pub fn put_maybe(&self, inner: T) -> Option<T> { |
|
if self.lock.load(Ordering::Relaxed) == true { |
|
if let Ok(_) = self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) { |
|
unsafe { &mut *self.inner.get() }.insert(inner); |
|
None |
|
} else { |
|
Some(inner) |
|
} |
|
} else { |
|
Some(inner) |
|
} |
|
} |
|
}
|
|
|