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

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)
}
}
}