Acquire a lock instead of unwrapping it

Jan 30, 2023

A useful pattern I keep seeing around the internet for unwrapping Mutex and RwLock locks is to alias the unwrap for LockResult:

use std::sync::LockResult;

trait LockResultExt<T> {
  fn acquire(self) -> T;
}

impl<T> LockResultExt<T> for LockResult<T> {
  fn acquire(self) -> T {
    self.unwrap()
  }
}

let num: RwLock<usize> = RwLock::new(10);
*num.write().acquire() = 20;
println!("{}", num.read().acquire());

Because LockResult will only ever be an Err variant when there is a panic while an exclusive lock is in scope (for RwLocks), or when a lock is in scope (for Mutexes), we can unwrap the result so that any panic is propagated.

Additionally, PoisonError has an into_inner() function which allows you to recover the guard and have access to the data:

impl<T> LockResultExt<T> for LockResult<T> {
  fn acquire(self) -> T {
    match self {
      Ok(t) => t,
      Err(e) => e.into_inner(),
    }
  }
}