-
Notifications
You must be signed in to change notification settings - Fork 20
Add Mutex
and RwLock
APIs for accessing values within a function scope
#497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Returning |
|
What would you do with the (and yes, it's weird because the poison has nothing to do with the |
I don’t have a real use case for returning |
True, but also unlike #485 and this ACP, these two methods still return a In our case, there are two typical yet distinct choices when dealing with poison:
The proposed API cannot fulfill the second choice. So I think both use cases can be supported only if it was split into a 2-step process, the first step to handle the poison, and the second step to operate on the actual data. That seems like we should add the functions on the guard itself: let result_poisoned = mutex
.lock()
.unwrap()
.with(f);
let result_disinfected = mutex
.lock()
.match { // allow RFC #3295 already
Ok(guard) => guard,
Err(e) => e.into_inner()
}
.with(f); However, a let result_poisoned = MutexGuard::with(mutex.lock().unwrap(), f); (╯°□°)╯︵ ┻━┻ at this point why not just directly write let result_poisoned = f(&mut mutex.lock().unwrap()); |
#485 has already introduced such a case in
Based on this comment in #485, I assume the standard library team don’t want a API that ignores poisoning in the current lock types.
This is exactly the situation I would like to avoid. The mutex guard will only be dropped after the entire statement being evaluated. You can imagine cases like: let result_poisoned = f(&mut mutex.lock().unwrap());
g(result_poisoned); Without a comment explaining the lock guard should be dropped as soon as possible, someone could rewrite the code above into: g(f(&mut mutex.lock().unwrap())); Unless the users have studied the drop order rules, it might be hard for them to notice that let result_poisoned = mutex.with_mut(f).unwrap();
g(result_poisoned); Rewriting the code above in the same way will not extend the scope where the lock is being held: g(mutex.with_mut(f).unwrap()); |
rust-lang/rust#133406 is not yet approved even
Yeah for sure no one wants a The situation here is that
I'm not saying these are bad primitives, but either documentation of |
Note that the Mutex examples already show how to achieve this by using blocks. let result = {
let mut data = data_mutex_clone.lock().unwrap();
// This is the result of some important and long-ish work.
let result = data.iter().fold(0, |acc, x| acc + x * 2);
data.push(result);
result
// The mutex guard gets dropped here, together with any other values
// created in the critical section.
}; |
A block does not always work, for example, if the let result = { mutex.lock().unwrap().iter().fold(0, |acc, x| acc + x * 2) } + {
mutex.lock().unwrap().iter().fold(0, |acc, x| acc + x * 2)
}; You have to rewrite the code as: let result = {
let guard = mutex.lock().unwrap();
guard.iter().fold(0, |acc, x| acc + x * 2)
} + {
let guard = mutex.lock().unwrap();
guard.iter().fold(0, |acc, x| acc + x * 2)
}; Comments may also need to be added to prevent someone else from refactoring it into the first one. |
We discussed this in the libs-api meeting: considering the complexity around poisoning, we feel that that a "with" API should only be added to non-poisoning mutexes as proposed in #169. As such, we are partially accepting this ACP, and rejecting it for poisoning mutexes. |
Proposal
Problem statement
This is a follow-up on #485 to add a set of more generalized APIs for accessing values inside lock objects.
Motivating examples or use cases
The most common pattern to access the value inside a lock object is:
A problem is that the dropping of lock guards is often implicit, the scope where the lock object being held is not visually apparent, increasing the risk of locks being held for longer than necessary. For example in the code below, uses may not always realize that the
mutex_1
is unlocked after themutex_2
.Not only
guard_1
is held longer than necessary, also if some other thread acquire theseMutex
s in a different order, deadlock could happen.Solution sketch
Add the following APIs to the standard library.
With the proposed APIs above, the original example can be rewritten as:
In this way, the scope where the lock being held is more clear to user.
Alternatives
None.
Links and related work
This proposal is originally from: rust-lang/rust#133407 (comment).
What happens now?
This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.
Possible responses
The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):
Second, if there's a concrete solution:
The text was updated successfully, but these errors were encountered: