Skip to content

Instantly share code, notes, and snippets.

@unpluggedcoder
Created July 23, 2020 03:37
Show Gist options
  • Save unpluggedcoder/10106a82d7b72850d95de603d10aedc9 to your computer and use it in GitHub Desktop.
Save unpluggedcoder/10106a82d7b72850d95de603d10aedc9 to your computer and use it in GitHub Desktop.
Simple SpinLock written by Rust
// https://github.com/koute/memory-profiler/blob/master/preload/src/spin_lock.rs
use std::sync::atomic::{AtomicBool, Ordering};
use std::ops::{Deref, DerefMut};
use std::cell::UnsafeCell;
use std::mem::transmute;
pub struct SpinLock< T > {
pub value: UnsafeCell< T >,
pub flag: AtomicBool
}
unsafe impl< T > Send for SpinLock< T > {}
unsafe impl< T > Sync for SpinLock< T > {}
pub struct SpinLockGuard< 'a, T: 'a >( &'a SpinLock< T > );
impl< T > SpinLock< T > {
pub const fn new( value: T ) -> Self {
SpinLock {
value: UnsafeCell::new( value ),
flag: AtomicBool::new( false )
}
}
pub fn lock( &self ) -> SpinLockGuard< T > {
while self.flag.compare_and_swap( false, true, Ordering::Acquire ) != false {
}
SpinLockGuard( self )
}
pub fn try_lock( &self ) -> Option< SpinLockGuard< T > > {
if self.flag.compare_and_swap( false, true, Ordering::Acquire ) == false {
Some( SpinLockGuard( self ) )
} else {
None
}
}
pub unsafe fn unsafe_as_ref( &self ) -> &T {
&*self.value.get()
}
pub unsafe fn force_unlock( &self ) {
self.flag.store( false, Ordering::SeqCst );
}
}
impl< 'a, T > SpinLockGuard< 'a, T > {
#[allow(dead_code)]
pub fn unwrap( self ) -> Self {
self
}
}
impl< 'a, T > SpinLockGuard< 'a, *mut T > {
#[allow(dead_code)]
pub unsafe fn as_ref( self ) -> SpinLockGuard< 'a, &'a T > {
transmute( self )
}
}
impl< 'a, T > Drop for SpinLockGuard< 'a, T > {
fn drop( &mut self ) {
self.0.flag.store( false, Ordering::Release );
}
}
impl< 'a, T > Deref for SpinLockGuard< 'a, T > {
type Target = T;
fn deref( &self ) -> &Self::Target {
unsafe {
transmute( self.0.value.get() )
}
}
}
impl< 'a, T > DerefMut for SpinLockGuard< 'a, T > {
fn deref_mut( &mut self ) -> &mut Self::Target {
unsafe {
transmute( self.0.value.get() )
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment