Skip to content

Instantly share code, notes, and snippets.

@magniff
Created May 13, 2023 18:49
Show Gist options
  • Select an option

  • Save magniff/cfe6a42a1a46705cf4fabedfd47d9ef5 to your computer and use it in GitHub Desktop.

Select an option

Save magniff/cfe6a42a1a46705cf4fabedfd47d9ef5 to your computer and use it in GitHub Desktop.
Spinlock in Rust
use std::cell::UnsafeCell;
use std::sync::atomic::{AtomicBool, Ordering};
static UNLOCKED: bool = false;
static LOCKED: bool = true;
struct SpinLock<T> {
inner: UnsafeCell<T>,
state: AtomicBool,
}
struct SpinLockGuard<'a, T> {
lock: &'a SpinLock<T>,
}
impl<'a, T> std::ops::Deref for SpinLockGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.lock.inner.get() }
}
}
impl<'a, T> std::ops::DerefMut for SpinLockGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.lock.inner.get() }
}
}
impl<'a, T> SpinLockGuard<'a, T> {
pub fn new(lock: &'a SpinLock<T>) -> Self {
Self { lock }
}
}
impl<'a, T> Drop for SpinLockGuard<'a, T> {
fn drop(&mut self) {
self.lock.state.store(UNLOCKED, Ordering::Release);
}
}
impl<T> SpinLock<T> {
pub fn lock<'a>(&'a self) -> SpinLockGuard<'a, T> {
while self
.state
.compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
std::hint::spin_loop()
}
SpinLockGuard::new(self)
}
pub fn new(value: T) -> Self {
SpinLock {
inner: UnsafeCell::new(value),
state: AtomicBool::new(UNLOCKED),
}
}
}
unsafe impl<T> Sync for SpinLock<T> where T: Send {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment