Description
Proposal
Problem statement
Currently, if you are to use any of the locks provided by the standard library, you are forced to handle lock poisoning.
Most of the time you aren't really interested in maneging these, so you're left with two options:
- Unwrap the result of the lock
- Take the lock from the returned error (with
std::sync::PoisonError::into_inner
)
Motivation, use-cases
use std::sync::*;
let hello = Mutex::new(2);
std::thread::scope(|s| {
s.spawn(|| {
let _guard = hello.lock();
panic!("Ups!");
});
// May return `Err`, if `_guard` is obtained before `guard2`
let guard2: LockResult<MutexGuard<i32>> = hello.lock();
})
This is the solution if you are to unwrap
/expect
the result
use std::sync::*;
let hello = Mutex::new(2);
std::thread::scope(|s| {
s.spawn(|| {
let _guard = hello.lock();
panic!("Ups!");
});
// May panic, if `_guard` is obtained before `guard2`
let guard2: MutexGuard<i32> = hello.lock().unwrap();
})
This is the solution if you are to take the lock from the error
use std::sync::*;
let hello = Mutex::new(2);
std::thread::scope(|s| {
s.spawn(|| {
let _guard = hello.lock();
panic!("Ups!");
});
// Never panics
let guard2: MutexGuard<i32> = match hello.lock() {
Ok(x) => x,
Err(e) => e.into_inner()
};
})
Solution sketches
Ideally, you should be using the last example if you aren't interested in managing poisonous locks, but having to make the same match expression every time you want to lock is very cumbersome, so perhaps we should add a method that makes the lock without checking if it's poisoned.
use std::sync::*;
let hello = Mutex::new(2);
std::thread::scope(|s| {
s.spawn(|| {
let _guard = hello.lock();
panic!("Ups!");
});
// Never panics (name is an example, and I'm sure a better one exists)
let guard2: MutexGuard<i32> = hello.lock_deep();
})
Another proposed solution is to create new lock types that would not implement poison-checking.
// Again, the name is probably improveable
pub struct DeepMutex<T: ?Sized> {
/* ... */
}
impl<T: ?Sized> DeepMutex<T> {
pub const fn new (t: T) -> Self where T: Sized { /* ... */ }
pub fn try_lock (&self) -> Option<DeepMutexGuard<'_, T>> { /* ... */ }
pub fn lock (&self) -> DeepMutexGuard<'_, T> { /* ... */ }
/* ... */
}
Links and related work
What happens now?
This issue is part of the libs-api team API change proposal process. Once this issue is filed the libs-api team will review open proposals in its weekly meeting. You should receive feedback within a week or two.
Activity