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