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 aOnceLock
and 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