lockfree_object_pool/
spin_lock.rs

1use std::cell::UnsafeCell;
2use std::ops::{Deref, DerefMut};
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::thread;
5
6pub struct SpinLock<T> {
7    data: UnsafeCell<T>,
8    lock: AtomicBool,
9}
10
11impl<T> SpinLock<T> {
12    #[inline]
13    pub fn new(data: T) -> Self {
14        Self {
15            data: UnsafeCell::new(data),
16            lock: AtomicBool::new(false),
17        }
18    }
19
20    #[inline]
21    pub fn lock(&self) -> SpinLockGuard<T> {
22        self.acquire();
23        SpinLockGuard { lock: self }
24    }
25
26    #[inline]
27    fn acquire(&self) {
28        self.exchange(false, true);
29    }
30
31    #[inline]
32    fn release(&self) {
33        self.exchange(true, false);
34    }
35
36    #[inline]
37    fn exchange(&self, from: bool, to: bool) {
38        loop {
39            match self
40                .lock
41                .compare_exchange_weak(from, to, Ordering::SeqCst, Ordering::Relaxed)
42            {
43                Ok(_) => break,
44                Err(_) => {
45                    thread::yield_now();
46                }
47            }
48        }
49    }
50}
51
52unsafe impl<T: Send> Send for SpinLock<T> {} // SAFETY: sending the data is allowed if it's Send
53unsafe impl<T: Send> Sync for SpinLock<T> {} // SAFETY: the Mutex manages synchronization so only Send is required
54
55pub struct SpinLockGuard<'a, T> {
56    lock: &'a SpinLock<T>,
57}
58
59impl<'a, T> DerefMut for SpinLockGuard<'a, T> {
60    #[inline]
61    fn deref_mut(&mut self) -> &mut Self::Target {
62        unsafe {
63            // SAFETY: this is the only active guard
64            &mut *self.lock.data.get()
65        }
66    }
67}
68
69impl<'a, T> Deref for SpinLockGuard<'a, T> {
70    type Target = T;
71
72    #[inline]
73    fn deref(&self) -> &Self::Target {
74        unsafe {
75            // SAFETY: this is the only active guard
76            &*self.lock.data.get()
77        }
78    }
79}
80
81impl<'a, T> Drop for SpinLockGuard<'a, T> {
82    #[inline]
83    fn drop(&mut self) {
84        self.lock.release();
85    }
86}
87
88unsafe impl<T: Send> Send for SpinLockGuard<'_, T> {} // SAFETY: normal rules apply
89unsafe impl<T: Sync> Sync for SpinLockGuard<'_, T> {} // SAFETY: normal rules apply