-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Implement MappedMutexGuard
, MappedRwLockReadGuard
, and MappedRwLockWriteGuard
.
#117107
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
/RwLockState
structsHavingIf this is not desired, thensys::(Mutex|RwLock)
andpoison::Flag
as separate fields in theMutex
/RwLock
would requireMappedMutexGuard
/MappedRwLockWriteGuard
to hold an additional pointer, so I combined the two fields into aMutexState
/RwLockState
struct. This should not noticeably affect perf or layout, but requires an additional field projection when accessing the former.inner
or.poison
fields (now.state.inner
and.state.poison
).MappedMutexGuard
/MappedRwLockWriteGuard
can instead hold separate pointers to the two fields.The doc-comments are mostly copied from the existing
*Guard
doc-comments, with some parts fromlock_api::Mapped*Guard
's doc-comments.Unresolved question: Are more tests needed?