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}