option_lock/
arc.rs

1use alloc::sync::Arc;
2use core::{
3    fmt::{self, Debug, Formatter},
4    mem,
5    ops::{Deref, DerefMut},
6};
7
8use super::lock::{OptionGuard, OptionLock};
9use super::mutex::{Mutex, MutexGuard};
10
11/// A write guard for the value of an [`Arc<OptionLock>`]
12pub struct OptionGuardArc<T> {
13    lock: Arc<OptionLock<T>>,
14    filled: bool,
15}
16
17impl<T> OptionGuardArc<T> {
18    #[inline]
19    pub(crate) fn new(lock: Arc<OptionLock<T>>, guard: OptionGuard<'_, T>) -> Self {
20        let result = Self {
21            lock,
22            filled: guard.is_some(),
23        };
24        mem::forget(guard);
25        result
26    }
27
28    /// Obtain a shared reference to the contained value, if any.
29    pub fn as_ref(&self) -> Option<&T> {
30        if self.filled {
31            Some(unsafe { &*self.lock.as_mut_ptr() })
32        } else {
33            None
34        }
35    }
36
37    /// Obtain an exclusive reference to the contained value, if any.
38    pub fn as_mut_ref(&mut self) -> Option<&mut T> {
39        if self.filled {
40            Some(unsafe { &mut *self.lock.as_mut_ptr() })
41        } else {
42            None
43        }
44    }
45
46    /// Check if the lock contains `None`.
47    #[inline]
48    pub fn is_none(&self) -> bool {
49        !self.filled
50    }
51
52    /// Check if the lock contains `Some(T)`.
53    #[inline]
54    pub fn is_some(&self) -> bool {
55        self.filled
56    }
57
58    /// Replace the value in the lock, returning the previous value, if any.
59    pub fn replace(&mut self, value: T) -> Option<T> {
60        let ret = if self.filled {
61            Some(unsafe { self.lock.as_mut_ptr().read() })
62        } else {
63            self.filled = true;
64            None
65        };
66        unsafe {
67            self.lock.as_mut_ptr().write(value);
68        }
69        ret
70    }
71
72    /// Take the current value from the lock, if any.
73    pub fn take(&mut self) -> Option<T> {
74        if self.filled {
75            self.filled = false;
76            Some(unsafe { self.lock.as_mut_ptr().read() })
77        } else {
78            None
79        }
80    }
81}
82
83impl<T: Debug> Debug for OptionGuardArc<T> {
84    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
85        f.debug_tuple("OptionGuardArc")
86            .field(&self.as_ref())
87            .finish()
88    }
89}
90
91impl<T> Drop for OptionGuardArc<T> {
92    fn drop(&mut self) {
93        let _ = OptionGuard::new(&self.lock, self.filled);
94    }
95}
96
97unsafe impl<T: Send> Send for OptionGuardArc<T> {}
98unsafe impl<T: Sync> Sync for OptionGuardArc<T> {}
99
100/// A write guard for an [`Arc<Mutex>`]
101pub struct MutexGuardArc<T> {
102    lock: Arc<Mutex<T>>,
103}
104
105impl<T> MutexGuardArc<T> {
106    #[inline]
107    pub(crate) fn new(lock: Arc<Mutex<T>>, guard: MutexGuard<'_, T>) -> Self {
108        let result = Self { lock };
109        mem::forget(guard);
110        result
111    }
112
113    /// Replace the value in the lock, returning the previous value.
114    pub fn replace(&mut self, value: T) -> T {
115        mem::replace(unsafe { &mut *self.lock.as_mut_ptr() }, value)
116    }
117}
118
119impl<T> Deref for MutexGuardArc<T> {
120    type Target = T;
121
122    fn deref(&self) -> &Self::Target {
123        unsafe { &*self.lock.as_ptr() }
124    }
125}
126
127impl<T> DerefMut for MutexGuardArc<T> {
128    fn deref_mut(&mut self) -> &mut Self::Target {
129        unsafe { &mut *self.lock.as_mut_ptr() }
130    }
131}
132
133impl<T: Debug> Debug for MutexGuardArc<T> {
134    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
135        f.debug_tuple("MutexGuardArc").field(&**self).finish()
136    }
137}
138
139impl<T> Drop for MutexGuardArc<T> {
140    fn drop(&mut self) {
141        let _ = OptionGuard::new(&self.lock.inner, true);
142    }
143}
144
145unsafe impl<T: Send> Send for MutexGuardArc<T> {}
146unsafe impl<T: Sync> Sync for MutexGuardArc<T> {}