1use core::cell::UnsafeCell;
2
3use crate::sync::raw_spin_lock::{RawSpinLock, RawSpinLockGuard};
4
5#[derive(Debug)]
20pub struct SpinLock<T> {
21 raw_lock: RawSpinLock,
22 data: UnsafeCell<T>,
23}
24
25impl<T> SpinLock<T> {
26 pub const fn new(data: T) -> Self {
28 SpinLock {
29 raw_lock: RawSpinLock::new(),
30 data: UnsafeCell::new(data),
31 }
32 }
33
34 pub fn lock(&self) -> SpinLockGuard<'_, T> {
36 let _raw_guard = self.raw_lock.lock();
37 SpinLockGuard {
38 _raw_guard,
39 data: unsafe { &mut *self.data.get() },
40 }
41 }
42
43 pub fn try_lock(&self) -> Option<SpinLockGuard<'_, T>> {
45 self.raw_lock.try_lock().map(|_raw_guard| SpinLockGuard {
46 _raw_guard,
47 data: unsafe { &mut *self.data.get() },
48 })
49 }
50
51 #[cfg(test)]
54 pub fn is_locked(&self) -> bool {
55 self.raw_lock.is_locked()
56 }
57}
58
59pub struct SpinLockGuard<'a, T> {
62 _raw_guard: RawSpinLockGuard<'a>,
63 data: &'a mut T,
64}
65
66impl<T> core::ops::Deref for SpinLockGuard<'_, T> {
67 type Target = T;
68
69 fn deref(&self) -> &Self::Target {
70 self.data
71 }
72}
73
74impl<T> core::ops::DerefMut for SpinLockGuard<'_, T> {
75 fn deref_mut(&mut self) -> &mut Self::Target {
76 self.data
77 }
78}
79
80unsafe impl<T: Send> Send for SpinLock<T> {}
83unsafe impl<T: Send> Sync for SpinLock<T> {}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::{kassert, println, test_case};
89
90 test_case!(test_spinlock_basic, {
92 println!("Testing: test_spinlock_basic");
93 let lock = SpinLock::new(0usize);
94
95 kassert!(!lock.is_locked());
97
98 {
100 let mut guard = lock.lock();
101 kassert!(lock.is_locked());
102 *guard = 42;
103 kassert!(*guard == 42);
104 } kassert!(!lock.is_locked());
108 });
109
110 test_case!(test_spinlock_relock_after_drop, {
112 println!("Testing: test_spinlock_relock_after_drop");
113 let lock = SpinLock::new(1usize);
114
115 {
116 let mut g1 = lock.lock();
117 *g1 += 1;
118 kassert!(*g1 == 2);
119 }
121
122 {
124 let mut g2 = lock.lock();
125 *g2 += 1;
126 kassert!(*g2 == 3);
127 }
128 kassert!(!lock.is_locked());
129 });
130}