Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,17 @@ impl<T> AtomicLazyCell<T> {
_ => None,
}
}
/// Borrows the contents of this lazy cell mutably for the duration of the
/// cell itself.
///
/// This function will return `Some` if the cell has been previously
/// initialized, and `None` if it has not yet been initialized.
pub fn borrow_mut(&mut self) -> Option<&mut T> {
match self.state.load(Ordering::Acquire) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Atomic op seems confusing here, perhaps get_mut will be more clear? https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.get_mut

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matklad sorry to necrobump this PR, but could you expand on why the atomic op is confusing? I'm not very well acquainted with the atomic operations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is confusing in a sense that we do atomic load when we don’t need one. We have &mut anyway, so additional synchronization power which comes from atomic load is unnecessary. Using extra power when there’s no need for it confuses me, as I think that there should be some real reason for it.

SOME => unsafe { &mut *self.inner.get() }.as_mut(),
_ => None,
}
}

/// Consumes this `LazyCell`, returning the underlying value.
pub fn into_inner(self) -> Option<T> {
Expand Down Expand Up @@ -571,6 +582,22 @@ mod tests {
assert_eq!(value, Some(1));
}

#[test]
fn test_atomic_borrow_mut() {
let mut lazycell = AtomicLazyCell::new();
assert!(lazycell.borrow_mut().is_none());

lazycell.fill(1).unwrap();
assert_eq!(lazycell.borrow_mut(), Some(&mut 1));

*lazycell.borrow_mut().unwrap() = 2;
assert_eq!(lazycell.borrow_mut(), Some(&mut 2));

// official way to reset the cell
lazycell = AtomicLazyCell::new();
assert!(lazycell.borrow_mut().is_none());
}

#[test]
fn test_atomic_already_filled_panic() {
let lazycell = AtomicLazyCell::new();
Expand Down