1use core::{cell::UnsafeCell, fmt::Debug, mem};
6
7use crate::error::take_errno;
8
9pub struct Mutex<T> {
12 pros_mutex: pros_sys::mutex_t,
13 data: Option<UnsafeCell<T>>,
14}
15unsafe impl<T: Send> Send for Mutex<T> {}
16unsafe impl<T> Sync for Mutex<T> {}
17
18impl<T> Mutex<T> {
19 pub fn new(data: T) -> Self {
21 let pros_mutex = unsafe { pros_sys::mutex_create() };
22
23 Self {
24 pros_mutex,
25 data: Some(UnsafeCell::new(data)),
26 }
27 }
28
29 pub fn lock(&self) -> MutexGuard<'_, T> {
32 if !unsafe { pros_sys::mutex_take(self.pros_mutex, pros_sys::TIMEOUT_MAX) } {
33 panic!("Mutex lock failed: {}", take_errno());
34 }
35
36 MutexGuard { mutex: self }
37 }
38
39 pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
41 let success = unsafe { pros_sys::mutex_take(self.pros_mutex, 0) };
42 success.then(|| MutexGuard::new(self))
43 }
44
45 pub fn into_inner(mut self) -> T {
47 let data = mem::take(&mut self.data).unwrap();
48 data.into_inner()
49 }
50
51 pub fn get_mut(&mut self) -> &mut T {
53 self.data.as_mut().unwrap().get_mut()
54 }
55}
56
57impl<T> Drop for Mutex<T> {
58 fn drop(&mut self) {
59 unsafe {
60 pros_sys::mutex_delete(self.pros_mutex);
61 }
62 }
63}
64
65impl<T> Debug for Mutex<T>
66where
67 T: Debug,
68{
69 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
70 struct Placeholder;
71 impl Debug for Placeholder {
72 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
73 f.write_str("<locked>")
74 }
75 }
76
77 let mut d = f.debug_struct("Mutex");
78 match self.try_lock() {
79 Some(guard) => d.field("data", &&*guard),
80 None => d.field("data", &Placeholder),
81 };
82 d.finish_non_exhaustive()
83 }
84}
85
86impl<T> Default for Mutex<T>
87where
88 T: Default,
89{
90 fn default() -> Self {
91 Self::new(T::default())
92 }
93}
94
95impl<T> From<T> for Mutex<T> {
96 fn from(value: T) -> Self {
97 Self::new(value)
98 }
99}
100
101#[derive(Debug)]
104pub struct MutexGuard<'a, T> {
105 mutex: &'a Mutex<T>,
106}
107
108impl<'a, T> MutexGuard<'a, T> {
109 const fn new(mutex: &'a Mutex<T>) -> Self {
110 Self { mutex }
111 }
112}
113
114impl<T> core::ops::Deref for MutexGuard<'_, T> {
115 type Target = T;
116 fn deref(&self) -> &T {
117 unsafe { &*self.mutex.data.as_ref().unwrap().get() }
118 }
119}
120
121impl<T> core::ops::DerefMut for MutexGuard<'_, T> {
122 fn deref_mut(&mut self) -> &mut T {
123 unsafe { &mut *self.mutex.data.as_ref().unwrap().get() }
124 }
125}
126
127impl<T> Drop for MutexGuard<'_, T> {
128 fn drop(&mut self) {
129 unsafe {
130 pros_sys::mutex_give(self.mutex.pros_mutex);
131 }
132 }
133}