-
Couldn't load subscription status.
- Fork 13.9k
Implement MappedMutexGuard, MappedRwLockReadGuard, and MappedRwLockWriteGuard.
#117107
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
Conversation
|
r? @m-ou-se (rustbot has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment was marked as resolved.
This comment was marked as resolved.
library/std/src/sync/mutex.rs
Outdated
| let mut orig = ManuallyDrop::new(orig); | ||
| let value = NonNull::from(f(&mut *orig)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this leak orig if f panics, leaving the lock permanently locked? I would also add a test for mutex_lock.map(|_| panic!()) or something like that.
The same applies to the other implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that makes sense (edit: that the panic behavior should be documented and tested). I've refactored it so that the "old" guard is only wrapped in ManuallyDrop after the closure completes, so panicking in the closure has the same effect as panicking while holding the guard normally (unlocks the guard; poisons for MutexGuard and RwLockWriteGuard, doesn't poison for RwLockReadGuard). I've also added tests for panicking in the closures.
| // was created, and have been upheld throughout `map` and/or `try_map`. | ||
| // The signature of the closure guarantees that it will not "leak" the lifetime of the reference | ||
| // passed to it. If the closure panics, the guard will be dropped. | ||
| let data = NonNull::from(f(unsafe { &mut *orig.lock.data.get() })); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(applies to all the (try_)map functions) I used the unsafe here instead of just &(mut) *orig to be clearer that the lifetime of the reference is longer than the lifetime of the orig variable itself. However I think the other version should still be sound, so I can change it back to that if it seems better.
It does noticeably affect layout: making the states a separate |
|
Yes, that's true, it can affect layout because it can add overall padding, I missed that. However, I'll go ahead and revert the @rustbot author |
(makes implementing `Mapped*Guard` easier)
9d81136 to
3ef4b08
Compare
This comment has been minimized.
This comment has been minimized.
|
@rustbot ready Changed to holding separate references to the raw lock and the poison flag in Possible future optimization#[repr(C)]
struct Mutex<T: ?Sized> {
inner: sys::Mutex,
poison: poison::Flag,
data: UnsafeCell<T>,
}With this hypothetical definition of (Similar for |
Co-authored-by: Amanieu d'Antras <amanieu@gmail.com>
|
@bors r+ |
|
🌲 The tree is currently closed for pull requests below priority 50. This pull request will be tested once the tree is reopened. |
|
☀️ Test successful - checks-actions |
1 similar comment
|
☀️ Test successful - checks-actions |
|
Finished benchmarking commit (a2f3c0c): comparison URL. Overall result: ❌ regressions - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 651.212s -> 650.238s (-0.15%) |
|
Miri's run of the test suite showed new UB on apple for today's nightly, just after this PR landed. Could this bug have been introduced by this PR? Also see Zulip |
|
Hm, the test in question does not use the |
ACP: rust-lang/libs-team#260
Tracking issue: #117108
(Outdated)
MutexState/RwLockStatestructsHavingIf this is not desired, thensys::(Mutex|RwLock)andpoison::Flagas separate fields in theMutex/RwLockwould requireMappedMutexGuard/MappedRwLockWriteGuardto hold an additional pointer, so I combined the two fields into aMutexState/RwLockStatestruct. This should not noticeably affect perf or layout, but requires an additional field projection when accessing the former.inneror.poisonfields (now.state.innerand.state.poison).MappedMutexGuard/MappedRwLockWriteGuardcan instead hold separate pointers to the two fields.The doc-comments are mostly copied from the existing
*Guarddoc-comments, with some parts fromlock_api::Mapped*Guard's doc-comments.Unresolved question: Are more tests needed?