Struct twice_cell::TwiceLock
source · pub struct TwiceLock<A, B> { /* private fields */ }Implementations§
source§impl<A, B> TwiceLock<A, B>
impl<A, B> TwiceLock<A, B>
sourcepub fn get(&self) -> Option<&B>
pub fn get(&self) -> Option<&B>
Gets the reference to the underlying value.
Returns None if the cell is unset, or being set.
This method never blocks.
sourcepub fn get_mut(&mut self) -> Option<&mut B>
pub fn get_mut(&mut self) -> Option<&mut B>
Gets the mutable reference to the underlying value.
Returns None if the cell is unset. This method never blocks.
sourcepub fn get_either_mut(&mut self) -> Either<&mut A, &mut B> ⓘ
pub fn get_either_mut(&mut self) -> Either<&mut A, &mut B> ⓘ
Gets the mutable reference to either underlying value.
sourcepub fn set(&self, value: B) -> Result<(), B>where
A: RefUnwindSafe,
pub fn set(&self, value: B) -> Result<(), B>where
A: RefUnwindSafe,
Sets the contents of this cell to value.
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.
§Errors
Returns Ok(()) if the cell’s value was set by this call.
§Examples
use twice_cell::TwiceLock;
static CELL: TwiceLock<&str, i32> = TwiceLock::new("initial value");
fn main() {
assert!(CELL.get().is_none());
std::thread::spawn(|| {
assert_eq!(CELL.set(92), Ok(()));
}).join().unwrap();
assert_eq!(CELL.set(62), Err(62));
assert_eq!(CELL.get(), Some(&92));
}sourcepub fn try_insert(&self, value: B) -> Result<&B, (&B, B)>where
A: RefUnwindSafe,
pub fn try_insert(&self, value: B) -> Result<&B, (&B, B)>where
A: RefUnwindSafe,
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.
§Errors
Returns Ok(&value) if the cell was empty and Err(¤t_value, value) if it was full.
§Examples
use twice_cell::TwiceLock;
static CELL: TwiceLock<&'static str, i32> = TwiceLock::new("initial value");
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));
}sourcepub fn get_or_init<F>(&self, f: F) -> &B
pub fn get_or_init<F>(&self, f: F) -> &B
Gets the contents of the cell, initializing it with f if the cell
was empty.
Many threads may call get_or_init concurrently with different
initializing functions, but it is guaranteed that only one function
will be executed.
§Panics
If f panics, the panic is propagated to the caller, and the cell
remains uninitialized.
It is an error to reentrantly initialize the cell from f. The
exact outcome is unspecified. Current implementation deadlocks, but
this may be changed to a panic in the future.
§Examples
use twice_cell::TwiceLock;
let cell = TwiceLock::new("initial value");
let value = cell.get_or_init(|s| s.len());
assert_eq!(value, &13);
let value = cell.get_or_init(|_| unreachable!());
assert_eq!(value, &13);sourcepub fn get_mut_or_init<F>(&mut self, f: F) -> &mut B
pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut B
Gets the mutable reference of the contents of the cell, initializing
it with f if the cell was empty.
Many threads may call get_mut_or_init concurrently with different
initializing functions, but it is guaranteed that only one function
will be executed.
§Panics
If f panics, the panic is propagated to the caller, and the cell
remains uninitialized.
§Examples
use twice_cell::TwiceLock;
let mut cell = TwiceLock::new("initial value");
let value = cell.get_mut_or_init(|s| s.len());
assert_eq!(*value, 13);
*value += 2;
assert_eq!(*value, 15);
let value = cell.get_mut_or_init(|_| unreachable!());
assert_eq!(*value, 15);sourcepub fn get_or_try_init<F, E>(&self, f: F) -> Result<&B, E>
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&B, E>
Gets the contents of the cell, initializing it with f if
the cell was empty.
§Panics
If f panics, the panic is propagated to the caller, and
the cell remains uninitialized.
§Errors
If the cell was empty and f failed, an error is returned.
It is an error to reentrantly initialize the cell from f.
The exact outcome is unspecified. Current implementation
deadlocks, but this may be changed to a panic in the future.
§Examples
use twice_cell::TwiceLock;
let cell = TwiceLock::new("initial value");
assert_eq!(cell.get_or_try_init(|_| Err(())), Err(()));
assert!(cell.get().is_none());
let value = cell.get_or_try_init(|s| -> Result<usize, ()> {
Ok(s.len())
});
assert_eq!(value, Ok(&13));
assert_eq!(cell.get(), Some(&13))sourcepub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut B, E>
pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut B, E>
Gets the mutable reference of the contents of the cell, initializing
it with f if the cell was empty.
§Panics
If f panics, the panic is propagated to the caller, and
the cell remains uninitialized.
§Errors
If the cell was empty and f failed, an error is returned.
§Examples
use twice_cell::TwiceLock;
let mut cell: TwiceLock<&'static str, usize> = TwiceLock::new("not a number");
// Failed initializers do not change the value
assert!(cell.get_mut_or_try_init(|s| s.parse()).is_err());
assert!(cell.get().is_none());
let value = cell.get_mut_or_try_init(|_| "1234".parse());
assert_eq!(value, Ok(&mut 1234));
*value.unwrap() += 2;
assert_eq!(cell.get(), Some(&1236));sourcepub fn replace(&mut self, value: A) -> Either<A, B> ⓘ
pub fn replace(&mut self, value: A) -> Either<A, B> ⓘ
Takes the value out of this TwiceLock, moving it back to an unset state.
Returns Either::Left if the TwiceLock hasn’t been set.
Safety is guaranteed by requiring a mutable reference.
§Examples
use twice_cell::TwiceLock;
use either::Either;
let mut cell: TwiceLock<i32, String> = TwiceLock::new(123);
assert_eq!(cell.replace(456), Either::Left(123));
let mut cell = TwiceLock::new(123);
cell.set("hello").unwrap();
assert_eq!(cell.replace(456), Either::Right("hello"));
assert_eq!(cell.get(), None);Trait Implementations§
impl<A: Send, B: Send> Send for TwiceLock<A, B>
Safety: The UnsafeCell exists to enforce borrow checking via the Once primitive instead of the compiler;
that is to say, we can override UnsafeCell’s !Send-ness if both A and B are Send.
impl<A: Sync + Send, B: Sync + Send> Sync for TwiceLock<A, B>
Safety: The same is true for Sync, except that we also need A and B to impl Send for the same reason
there’s Send bounds on the OnceLock implementation:
Why do we need
T: Send? Thread A creates aOnceLockand shares it with scoped thread B, which fills the cell, which is then destroyed by A. That is, destructor observes a sent value.
Auto Trait Implementations§
impl<A, B> !Freeze for TwiceLock<A, B>
impl<A, B> !RefUnwindSafe for TwiceLock<A, B>
impl<A, B> Unpin for TwiceLock<A, B>
impl<A, B> UnwindSafe for TwiceLock<A, B>where
A: UnwindSafe,
B: UnwindSafe,
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more