diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2023-10-14 22:35:05 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-14 22:35:05 +0200 |
| commit | fcd75ccc90c23a7d669929e983c47ac0157a6d69 (patch) | |
| tree | 990a41cbc4a535d69c1eb4ad8ced1ae86a0e88aa /library/std/src | |
| parent | ee8c9d3c34719a129f280cd91ba5d324017bb02b (diff) | |
| parent | dd34d9027af3c0286aa038a365ff14387a6bf80c (diff) | |
| download | rust-fcd75ccc90c23a7d669929e983c47ac0157a6d69.tar.gz rust-fcd75ccc90c23a7d669929e983c47ac0157a6d69.zip | |
Rollup merge of #116540 - daxpedda:once-cell-lock-try-insert, r=Mark-Simulacrum
Implement `OnceCell/Lock::try_insert()` I took inspiration from [`once_cell`](https://crates.io/crates/once_cell): - [`once_cell::unsync::OnceCell::try_insert()`](https://github.com/matklad/once_cell/blob/874f9373abd7feaf923a3b3c34bfb3383529c671/src/lib.rs#L551-L563) - [`once_cell::sync::OnceCell::try_insert()`](https://github.com/matklad/once_cell/blob/874f9373abd7feaf923a3b3c34bfb3383529c671/src/lib.rs#L1080-L1087) I tried to change as little code as possible in the first commit and applied some obvious optimizations in the second one. ACP: https://github.com/rust-lang/libs-team/issues/276 Tracking issue: #116693
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/sync/once_lock.rs | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index e2b7b893cb5..f4963090795 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -126,11 +126,48 @@ impl<T> OnceLock<T> { #[inline] #[stable(feature = "once_cell", since = "1.70.0")] pub fn set(&self, value: T) -> Result<(), T> { + match self.try_insert(value) { + Ok(_) => Ok(()), + Err((_, value)) => Err(value), + } + } + + /// Sets the contents of this cell to `value` if the cell was empty, then + /// returns a reference to it. + /// + /// May block if another thread is currently attempting to initialize the cell. The cell is + /// guaranteed to contain a value when set returns, though not necessarily the one provided. + /// + /// Returns `Ok(&value)` if the cell was empty and `Err(¤t_value, value)` if it was full. + /// + /// # Examples + /// + /// ``` + /// #![feature(once_cell_try_insert)] + /// + /// use std::sync::OnceLock; + /// + /// static CELL: OnceLock<i32> = OnceLock::new(); + /// + /// fn main() { + /// assert!(CELL.get().is_none()); + /// + /// std::thread::spawn(|| { + /// assert_eq!(CELL.try_insert(92), Ok(&92)); + /// }).join().unwrap(); + /// + /// assert_eq!(CELL.try_insert(62), Err((&92, 62))); + /// assert_eq!(CELL.get(), Some(&92)); + /// } + /// ``` + #[inline] + #[unstable(feature = "once_cell_try_insert", issue = "116693")] + pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> { let mut value = Some(value); - self.get_or_init(|| value.take().unwrap()); + let res = self.get_or_init(|| value.take().unwrap()); match value { - None => Ok(()), - Some(value) => Err(value), + None => Ok(res), + Some(value) => Err((res, value)), } } |
