Looks like the author missed my main complaint about Rust mutexes, which is that the lock
method returns a Result
. There should be a try_unlock
method for when someone actually wants to handle the rather obscure failure case, and the name lock
should be used for a method that panics on failure but returns a value that doesn’t need to be unwrapped first. I see the current arrangement as being about as sensible as having array subscripting return a Result
to handle the case of a failed bounds check.
If lock-ergonomicsⓒ is as relevant to you as indexing, you’re doing it wrong.
I would rather take indexing returning Result
s than the other way around.
One can always wrap any code in {||{ //.. }}()
and use question marks liberally anyway (I call them stable try blocks 😉).
I kind of disagree here. .lock()
has the following behavior:
panic()
if the lock is already held by this thread - should never happen- error - if the current lock holder paniced
The second case is incredibly rare, so it’s one of the few cases where I think .unwrap()
makes sense in production code. But it should be an option to handle it in robust code that should never go down. This is rare, but it’s not so rare that we should force all locks to exist in a context where we can recover from panics.
.try_unlock()
should never exist because there should only be one way to release a lock: drop()
. Having a way to maybe unlock a mutex adds a ton of issues. If we assume this was a typo, .try_lock()
absolutely exists, and it’s for a non-blocking lock.
try_lock
already exists; it’s called lock
. I just want a more convenient name and I want the name of the new method to be lock
, but that ship has sailed.
if you’re really that bothered…
use std::sync::{Mutex, MutexGuard};
trait ULock<'a> {
type Guard;
fn ulock(&'a self) -> Self::Guard;
}
impl<'a, T: 'a> ULock<'a> for Mutex<T> {
type Guard = MutexGuard<'a, T>;
fn ulock(&'a self) -> Self::Guard {
self.lock().unwrap()
}
}
or use a wrapper struct, if you really really want the method to be called exactly lock
.