lock_free_static/
once_mut.rs1use crate::{Mutex, MutexGuard, OnceCell};
2use core::cell::Cell;
3
4pub 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 pub const fn new() -> Self {
18 Self {
19 cell: OnceCell::new(),
20 }
21 }
22
23 pub fn set(&self, value: T) -> Result<(), T> {
27 self.cell.set(Mutex::new(value)).map_err(Mutex::into_inner)
28 }
29
30 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 pub fn take(&mut self) -> Option<T> {
48 self.cell.take().map(Mutex::into_inner)
49 }
50
51 pub fn get_ptr(&self) -> Option<*mut T> {
55 self.cell.get().map(Mutex::get_ptr)
56 }
57
58 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 pub fn lock(&self) -> Option<LockGuard<'_, T>> {
74 self.cell.get().and_then(Mutex::try_lock)
75 }
76
77 pub fn into_inner(mut self) -> Option<T> {
81 self.take()
82 }
83}
84
85pub 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}