Skip to main content

conc_util/sync/
spinlock.rs

1use core::{
2    cell::UnsafeCell,
3    ops::{Deref, DerefMut},
4    sync::atomic::{AtomicBool, Ordering},
5};
6
7pub struct SpinLock<T = ()>(AtomicBool, UnsafeCell<T>);
8
9// SAFETY: UnsafeCell is only accessed when locked atomically.
10unsafe impl Sync for SpinLock {}
11
12impl<T> SpinLock<T> {
13    pub fn new(data: T) -> Self {
14        Self(AtomicBool::new(false), UnsafeCell::new(data))
15    }
16
17    pub fn lock<'a>(&'a self) -> SpinLockScope<'a, T> {
18        while self.0.swap(true, Ordering::AcqRel) {}
19        // SAFETY: spinlock above guarantees unique access
20        let locked = unsafe { self.1.get().as_mut_unchecked() };
21        SpinLockScope(&self.0, locked)
22    }
23}
24
25pub struct SpinLockScope<'a, T>(&'a AtomicBool, &'a mut T);
26
27impl<'a, T> Drop for SpinLockScope<'a, T> {
28    fn drop(&mut self) {
29        self.0.store(false, Ordering::Release);
30    }
31}
32
33impl<'a, T> Deref for SpinLockScope<'a, T> {
34    type Target = T;
35
36    fn deref(&self) -> &Self::Target {
37        self.1
38    }
39}
40
41impl<'a, T> DerefMut for SpinLockScope<'a, T> {
42    fn deref_mut(&mut self) -> &mut Self::Target {
43        self.1
44    }
45}