Created
May 13, 2023 18:49
-
-
Save magniff/cfe6a42a1a46705cf4fabedfd47d9ef5 to your computer and use it in GitHub Desktop.
Spinlock in Rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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