Skip to main content

lock_free_static/
once_mut.rs

1use crate::{Mutex, MutexGuard, OnceCell};
2use core::cell::Cell;
3
4/// Like [`OnceCell`](crate::OnceCell) but with exclusive mutable access to its content.
5pub struct OnceMut<T> {
6    cell: OnceCell<Mutex<T>>,
7}
8
9impl<T> Default for OnceMut<T> {
10    fn default() -> Self {
11        Self::new()
12    }
13}
14
15impl<T> OnceMut<T> {
16    /// Creates a new empty cell.
17    pub const fn new() -> Self {
18        Self {
19            cell: OnceCell::new(),
20        }
21    }
22
23    /// Sets the contents of this cell to `value`.
24    ///
25    /// Returns `Ok(())` if the cell’s value was set by this call.
26    pub fn set(&self, value: T) -> Result<(), T> {
27        self.cell.set(Mutex::new(value)).map_err(Mutex::into_inner)
28    }
29
30    /// Sets the contents of this cell to value returned by `ctor` call.
31    ///
32    /// The `ctor` is called only if the cell’s value is going set by this call. Otherwice `ctor` returned in `Err(..)`.
33    ///
34    /// # Panics
35    ///
36    /// If `ctor` panics, the panic is propagated to the caller, and the cell remains uninitialized.
37    pub fn set_with<F: FnOnce() -> T>(&self, ctor: F) -> Result<(), F> {
38        let cell = Cell::new(Some(ctor));
39        self.cell
40            .set_with(|| Mutex::new(cell.take().unwrap()()))
41            .map_err(|_| cell.take().unwrap())
42    }
43
44    /// Takes the value out of this cell, moving it back to an uninitialized state.
45    ///
46    /// Has no effect and returns `None` if the cell hasn’t been initialized.
47    pub fn take(&mut self) -> Option<T> {
48        self.cell.take().map(Mutex::into_inner)
49    }
50
51    /// Gets the pointer to the underlying value.
52    ///
53    /// Returns `None` if the cell is empty.
54    pub fn get_ptr(&self) -> Option<*mut T> {
55        self.cell.get().map(Mutex::get_ptr)
56    }
57
58    /// Gets the mutable reference to the underlying value.
59    ///
60    /// The main difference from [`OnceCell::get_mut`](`crate::OnceCell::get_mut`) is that `self` is taken as immutable.
61    ///
62    /// After this call returns `Some(..)`, all subsequent calls will return `None`, and there is no way to obtain mutable reference again.
63    pub fn get_mut(&self) -> Option<&mut T> {
64        self.cell
65            .get()
66            .and_then(Mutex::try_lock)
67            .map(MutexGuard::leak)
68    }
69
70    /// Gets a guarded mutable reference to the underlying value.
71    ///
72    /// Only one guard of the same value can exist at the same time.
73    pub fn lock(&self) -> Option<LockGuard<'_, T>> {
74        self.cell.get().and_then(Mutex::try_lock)
75    }
76
77    /// Consumes the cell, returning the wrapped value.
78    ///
79    /// Returns `None` if the cell was empty.
80    pub fn into_inner(mut self) -> Option<T> {
81        self.take()
82    }
83}
84
85/// [`OnceMut`] lock guard.
86pub type LockGuard<'a, T> = MutexGuard<'a, T>;
87
88#[cfg(test)]
89mod tests {
90    use super::OnceMut;
91
92    #[test]
93    fn get_mut() {
94        let cell = OnceMut::<i32>::new();
95        assert!(cell.get_mut().is_none());
96
97        cell.set(123).unwrap();
98
99        let value_mut = cell.get_mut().unwrap();
100        assert_eq!(*value_mut, 123);
101        assert!(cell.get_mut().is_none());
102        *value_mut = 321;
103        assert_eq!(*value_mut, 321);
104    }
105
106    #[test]
107    fn lock() {
108        let cell = OnceMut::<i32>::new();
109        assert!(cell.lock().is_none());
110
111        cell.set(123).unwrap();
112
113        let mut guard = cell.lock().unwrap();
114        assert_eq!(*guard, 123);
115        assert!(cell.lock().is_none());
116        *guard = 321;
117        assert_eq!(*guard, 321);
118        drop(guard);
119
120        assert_eq!(*cell.lock().unwrap(), 321);
121    }
122}