-
Notifications
You must be signed in to change notification settings - Fork 265
Add MappedArcMutexGuard to mirror MappedMutexGuard #496
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
base: master
Are you sure you want to change the base?
Changes from 8 commits
1722581
f7b78e4
38d305e
505c8b0
8419729
786173c
2d448fa
3adc6da
72d8521
2884cc7
6d1be01
230d8b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -108,6 +108,16 @@ pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, RawMutex, T>; | |
| /// thread. | ||
| pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>; | ||
|
|
||
| /// An RAII mutex guard returned by `ArcMutexGuard::map`, which can point to a | ||
| /// subfield of the protected data. | ||
| /// | ||
| /// The main difference between `MappedArcMutexGuard` and `ArcMutexGuard` is that the | ||
| /// former doesn't support temporarily unlocking and re-locking, since that | ||
| /// could introduce soundness issues if the locked object is modified by another | ||
| /// thread. | ||
| #[cfg(feature = "arc_lock")] | ||
| pub type MappedArcMutexGuard<U> = lock_api::MappedArcMutexGuard<RawMutex, U>; | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use crate::{Condvar, MappedMutexGuard, Mutex, MutexGuard}; | ||
|
|
@@ -311,6 +321,23 @@ mod tests { | |
| assert_eq!(contents, *(deserialized.lock())); | ||
| } | ||
|
|
||
| #[cfg(feature = "arc_lock")] | ||
| #[test] | ||
| fn test_arc_map() { | ||
| use lock_api::ArcMutexGuard; | ||
| use std::sync::Arc; | ||
|
|
||
| let contents: Vec<u8> = vec![0, 1, 2]; | ||
| let mutex = Arc::new(Mutex::new(contents)); | ||
|
|
||
| let guard = mutex.lock_arc(); | ||
| let mapped_guard = ArcMutexGuard::map(guard, |contents: &mut Vec<u8>| &mut contents[1]); | ||
| // The point of the ArcMutexGuard is that we don't borrow the mutex. | ||
| drop(mutex); | ||
|
|
||
| assert_eq!(*mapped_guard, 1); | ||
|
||
| } | ||
|
|
||
| #[test] | ||
| fn test_map_or_err_not_mapped() { | ||
| let mut map = HashMap::new(); | ||
|
|
||
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.
Rather than creating an allocation here, you could use
Arc::into_rawafter having turned the originalArcinto anArc<dyn Any>.Uh oh!
There was an error while loading. Please reload this page.
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.
I don't think I can turn a
Arc<T: ?Sized>into aArc<dyn Any>. If we could, we'd just need to directly store theArc<dyn Any>:)(I guess it's because the
*const ArcInner<T>insideArc<T>is already a fat pointer ifTis unsized, and rust doesn't have super-fat pointers to store both the size and the trait object vtable. Would be a neat addition though!)What I want is just the vtable for the drop glue, which trait objects include by default - so dropping the
Box<dyn Any>will properly decrement the Arc counter. Even if I turn theArc<Mutex<T>>into raw, I'm not sure how to decrement the counter during drop without knowing theTtype. All the decrement functions I see need theTtype at compile time, since they need to know what drop implementation to call.Could do that with a trait object of a dedicated trait that decrements the counter, but that's already what
Box<dyn Any>does.Uh oh!
There was an error while loading. Please reload this page.
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.
Well - we could start usingArc<dyn Any>everywhere, and downcasting to theMutexwhen we know the types. A bit more intrusive change.Nevermind we can't since we take the
Arc<Mutex<R, T>>from the user.EDIT: Also, I only now realize it's not just the conversion which is impossible, it's the representation itself. It's simply not possible to have a
Arc<dyn Any>where the actual value is unsized. So if we wanted to have aMutex<[u8]>, it could never be directly stored in aArc<dyn Any>:(Uh oh!
There was an error while loading. Please reload this page.
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.
We could require
T: Sizedspecifically for the arc-mapping functions, which would simplify a bit the code (and possibly relax this requirement in the future if we find a suitable solution).For now I added an example mapping a
ArcMutexGuard<Mutex<dyn Any>>to the concrete type, which requires an unsizedT.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.
I would be OK restricting the mapping functions to
T: Sizedif it can remove theBoxallocation. Unsized payloads (especially behind a mutex) are rarely used in practice anyways.Uh oh!
There was an error while loading. Please reload this page.
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.
I can update this PR for that. Will have it ready shortly. EDIT: Now pushed.
Of note, I do see a bunch of
Arc<Mutex<dyn ...>>on github, and these are all unsized.Of course we'd only prevent using
mapon them, so it wouldn't break anything (and many of them don't even use parking_lot), but I think there is a demand/use for unsized types in mutex in general.