Skip to content

Commit

Permalink
Avoid unnecessary synchronization in {force,deref}_mut
Browse files Browse the repository at this point in the history
  - `DerefMut` was not delegating to `force_mut()` (contary to the
    by-ref APIs);
  - `Lazy::force_mut` was not taking advantage of exclusive-mutability
    access, and instead paying shared-mutability access. Mainly, in the
    `sync` case, it involved atomic operations which are now skipped.

Fixes #226
  • Loading branch information
danielhenrymantilla committed May 28, 2023
1 parent 8c42266 commit 8f2d2f5
Showing 1 changed file with 18 additions and 8 deletions.
26 changes: 18 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,8 +796,14 @@ pub mod unsync {
/// assert_eq!(*lazy, 92);
/// ```
pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
Self::force(this);
Self::get_mut(this).unwrap_or_else(|| unreachable!())
if this.cell.get_mut().is_none() {
let value = match this.init.get_mut().take() {
Some(f) => f(),
None => panic!("Lazy instance has previously been poisoned"),
};
this.cell = OnceCell::with_value(value);
}
this.cell.get_mut().unwrap_or_else(|| unreachable!())
}

/// Gets the reference to the result of this lazy value if
Expand Down Expand Up @@ -844,8 +850,7 @@ pub mod unsync {

impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
fn deref_mut(&mut self) -> &mut T {
Lazy::force(self);
self.cell.get_mut().unwrap_or_else(|| unreachable!())
Lazy::force_mut(self)
}
}

Expand Down Expand Up @@ -1324,8 +1329,14 @@ pub mod sync {
/// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92);
/// ```
pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
Self::force(this);
Self::get_mut(this).unwrap_or_else(|| unreachable!())
if this.cell.get_mut().is_none() {
let value = match this.init.get_mut().take() {
Some(f) => f(),
None => panic!("Lazy instance has previously been poisoned"),
};
this.cell = OnceCell::with_value(value);
}
this.cell.get_mut().unwrap_or_else(|| unreachable!())
}

/// Gets the reference to the result of this lazy value if
Expand Down Expand Up @@ -1372,8 +1383,7 @@ pub mod sync {

impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
fn deref_mut(&mut self) -> &mut T {
Lazy::force(self);
self.cell.get_mut().unwrap_or_else(|| unreachable!())
Lazy::force_mut(self)
}
}

Expand Down

0 comments on commit 8f2d2f5

Please sign in to comment.