| 71 | |
| 72 | #[cold] |
| 73 | fn try_init<E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<&T, E> { |
| 74 | let _guard = OnceLockGuard::new(&self.mutex); |
| 75 | |
| 76 | // Check state again under lock |
| 77 | match self.state.load(Ordering::Acquire) { |
| 78 | UNINITIALIZED => { |
| 79 | self.state.store(INITIALIZING, Ordering::Release); |
| 80 | match f() { |
| 81 | Ok(val) => { |
| 82 | // SAFETY: We hold the lock and state is INITIALIZING |
| 83 | let ret = unsafe { &*(*self.val.get()).write(val) }; |
| 84 | self.state.store(INITIALIZED, Ordering::Release); |
| 85 | Ok(ret) |
| 86 | } |
| 87 | Err(e) => { |
| 88 | self.state.store(UNINITIALIZED, Ordering::Release); |
| 89 | Err(e) |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | INITIALIZED => { |
| 94 | // SAFETY: State is INITIALIZED, so val has been written |
| 95 | Ok(unsafe { (*self.val.get()).assume_init_ref() }) |
| 96 | } |
| 97 | _ => panic!("concurrent initialization"), |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | impl<T> Drop for OnceLock<T> { |