1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use std::cell::UnsafeCell;
use std::ops::{Deref, DerefMut};
use std::sync::atomic::{AtomicBool, Ordering};

pub struct SpinLock<T> {
    state: AtomicBool,
    data: UnsafeCell<T>,
}
impl<T> SpinLock<T> {
    pub fn new(val: T) -> Self {
        Self {
            state: AtomicBool::new(false),
            data: UnsafeCell::new(val),
        }
    }
    pub fn lock(&self) -> SpinLockGuard<'_, T> {
        while self
            .state
            .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
            .is_err()
        {
            std::hint::spin_loop();
        }
        SpinLockGuard {
            data_mut_borrow: unsafe { &mut *self.data.get() },
            state: self,
        }
    }
    pub(self) fn unlock(&self) {
        self.state.store(false, Ordering::Release);
    }
}

unsafe impl<T> Send for SpinLock<T> {}
unsafe impl<T> Sync for SpinLock<T> {}

pub struct SpinLockGuard<'a, T> {
    data_mut_borrow: &'a mut T,
    state: &'a SpinLock<T>,
}
impl<'a, T> Drop for SpinLockGuard<'a, T> {
    fn drop(&mut self) {
        self.state.unlock()
    }
}
impl<'a, T> Deref for SpinLockGuard<'a, T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        self.data_mut_borrow
    }
}
impl<'a, T> DerefMut for SpinLockGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.data_mut_borrow
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn synchronization() {
        use std::sync::Arc;
        let mut result = 1;
        for i in 1..=20000 {
            let s_lock = Arc::new(crate::SpinLock::new(result));
            let s_lock_sub = s_lock.clone();
            let spin = s_lock.clone();
            let t = std::thread::spawn(move || {
                let mut guard = s_lock.lock();
                *guard += 2;
            });
            let t2 = std::thread::spawn(move || {
                let mut guard = s_lock_sub.lock();
                *guard += 3;
            });
            t.join().unwrap();
            t2.join().unwrap();
            result = *spin.lock();
            assert_eq!(result, (i * 5) + 1);
        }
    }
    #[test]
    fn sync_ptr() {
        use std::sync::Arc;
        let mut result = 1;
        let b = Box::new(result);
        let mut_ptr = Box::into_raw(b);
        for i in 1..=20000 {
            let s_lock = Arc::new(crate::SpinLock::new(mut_ptr));
            let s_lock_sub = s_lock.clone();
            let spin = s_lock.clone();
            let t = std::thread::spawn(move || {
                let guard = s_lock.lock();
                let ptr = *guard;
                unsafe {
                    *ptr += 2;
                };
            });
            let t2 = std::thread::spawn(move || {
                let guard = s_lock_sub.lock();
                let ptr = *guard;
                unsafe {
                    *ptr += 3;
                };
            });
            t.join().unwrap();
            t2.join().unwrap();
            result = unsafe { **spin.lock() };
            assert_eq!(result, (i * 5) + 1);
        }
        unsafe { drop(Box::from_raw(mut_ptr)) };
    }
}