Implement OnceCell/Lock::try_insert()
This commit is contained in:
parent
bf9a1c8a19
commit
6db2587999
@ -87,10 +87,40 @@ pub fn get_mut(&mut self) -> Option<&mut T> {
|
||||
#[inline]
|
||||
#[stable(feature = "once_cell", since = "1.70.0")]
|
||||
pub fn set(&self, value: T) -> Result<(), T> {
|
||||
// SAFETY: Safe because we cannot have overlapping mutable borrows
|
||||
let slot = unsafe { &*self.inner.get() };
|
||||
if slot.is_some() {
|
||||
return Err(value);
|
||||
match self.try_insert(value) {
|
||||
Ok(_) => Ok(()),
|
||||
Err((_, value)) => Err(value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the contents of the cell to `value` if the cell was empty, then
|
||||
/// returns a reference to it.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method 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::cell::OnceCell;
|
||||
///
|
||||
/// let cell = OnceCell::new();
|
||||
/// assert!(cell.get().is_none());
|
||||
///
|
||||
/// assert_eq!(cell.try_insert(92), Ok(&92));
|
||||
/// assert_eq!(cell.try_insert(62), Err((&92, 62)));
|
||||
///
|
||||
/// assert!(cell.get().is_some());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "once_cell_try_insert", issue = "116693")]
|
||||
pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
|
||||
if let Some(old) = self.get() {
|
||||
return Err((old, value));
|
||||
}
|
||||
|
||||
// SAFETY: This is the only place where we set the slot, no races
|
||||
@ -99,7 +129,7 @@ pub fn set(&self, value: T) -> Result<(), T> {
|
||||
// maintains the `inner`'s invariant.
|
||||
let slot = unsafe { &mut *self.inner.get() };
|
||||
*slot = Some(value);
|
||||
Ok(())
|
||||
Ok(self.get().unwrap())
|
||||
}
|
||||
|
||||
/// Gets the contents of the cell, initializing it with `f`
|
||||
|
@ -126,11 +126,48 @@ pub fn get_mut(&mut self) -> Option<&mut 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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user