diff options
| author | Christian Cunningham <c@localhost> | 2022-08-26 17:24:34 -0700 |
|---|---|---|
| committer | Christian Cunningham <c@localhost> | 2022-08-26 17:24:34 -0700 |
| commit | 0579fb14ef4be4f9ccbb621758ba1d2d7235a489 (patch) | |
| tree | 513df6c0422f388882998e7fe0eaec2bdc8087b0 /src | |
| parent | 8e1ace2ce673a8f2d627843ff6424c4a0e3eea97 (diff) | |
Add Spinlock
Diffstat (limited to 'src')
| -rw-r--r-- | src/sync.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/sync.rs b/src/sync.rs index 0e0ace2..38cffc8 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -81,3 +81,59 @@ impl<T> interface::Mutex for NullLock<T> { f(data) } } + +use core::sync::atomic::{AtomicBool, Ordering}; + +pub struct SpinLock<T> +where + T: Sized, +{ + data: UnsafeCell<T>, + lock: AtomicBool, +} + +unsafe impl<T> Send for SpinLock<T> where T: Sized + Send {} +unsafe impl<T> Sync for SpinLock<T> where T: Sized + Send {} + +impl<T> SpinLock<T> { + /// # New lock + pub const fn new(data: T) -> Self { + Self { + data: UnsafeCell::new(data), + lock: AtomicBool::new(false), + } + } +} + +impl<T: interface::Initializable> SpinLock<T> { + /// # Init + pub fn init(&self) { + use interface::Mutex; + self.lock(|init| { + init.init(); + }); + } +} + +impl<T> interface::Mutex for SpinLock<T> { + /// # Data type + type Data = T; + /// # Lock + fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut T) -> R) -> R { + loop { + // Loop until acquired the lock + if let Ok(false) = + self.lock + .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) + { + break; + } + } + let data = unsafe { &mut *self.data.get() }; + + let res = f(data); + // Release the lock after finished with the underlying data + self.lock.store(false, Ordering::Release); + res + } +} |
