-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Add RwLockReadGuard::map for transforming guards to contain sub-borrows. #30834
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
I've opened this without an accompanying RFC since it's a simple, unstable API. Let me know if adding this as unstable would require an RFC and I can write one up. |
For reference, my current use case is a type which contains a |
14039a1
to
d18ccce
Compare
I would think these APIs should match the similar APIs on the NB. those have the functionality as associated functions, not methods: we try to avoid methods on generic smart-pointers/ Also, (I'm in favour of this.) |
Note: I have prepped a temporary fork of RwLock to get this API on stable for my personal use which I'll keep around until these changes become stabilized. (We have a rust in prod usecase that depends on this feature and we would like to compile on stable) Agreed with all of @huonw's comments, will update. |
If we're going to add this (which I have no real problem with), we should also stick this on |
Can do. |
Hmm, I am looking at this code again and I think there is a subtle bug - the original guard should be |
I think this is a definite improvement to the RwLock API, having found myself wanting something like this in my own code and being forced to approximate with unsafe code. I also agree with @sfackler that this should be added to the guards of various synchronization primitives, although the situation gets slightly hairier with In particular, I wonder whether it is possible or makes sense to actually downgrade an |
@rphmeier pthread rwlocks don't support a downgrade operation, unfortunately, so we wouldn't be able to support a |
@sfackler Ah, that's unfortunate. At the very least, |
This is very cool, I wanted something similar while writing floki. |
I believe we're good to go with this if the same method gets added to |
Ah yes sorry I meant to get to this sooner. We discussed this in the libs meeting and decided to move forward. We'd like to add this to the following types, though:
Also feel free to hook this up to this tracking issue: #27746 |
876f311
to
4385db1
Compare
Updated the PR to include the method as an associated function for |
I currently added the methods as unstable, but could change the PR to land them as insta-stable if that is desirable. |
I think we'll land them as unstable but stabilize at the same time as |
Ok, I changed them to use a common feature |
reason = "recently added, needs RFC for stabilization", | ||
issue = "0")] | ||
pub fn map<U: ?Sized, F>(this: Self, cb: F) -> RwLockReadGuard<'rwlock, U> | ||
where F: FnOnce(&'rwlock T) -> &'rwlock U { |
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.
Stylistically where clauses like this in the standard library tend to be formatted like:
pub fn map<F>(...) -> T
where F: ...
{
// ...
}
This is very useful when the lock is synchronizing access to a data structure and you would like to return or store guards which contain references to data inside the data structure instead of the data structure itself.
4385db1
to
a4343e9
Compare
where F: FnOnce(&'rwlock mut T) -> &'rwlock mut U { | ||
let new_data = unsafe { | ||
let data: &'rwlock mut T = &mut *this.__data.get(); | ||
mem::transmute::<&'rwlock mut U, &'rwlock UnsafeCell<U>>(cb(data)) |
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.
The strategy above of changing the stored type to just T
seemed to work out well, could that be done here to avoid the transmute?
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'll change both RwLockWriteGuard
and MutexGuard
to store &mut T
s.
93d78ab
to
bf60078
Compare
Ok, I think this should be ready to land now. |
/// ``` | ||
#[unstable(feature = "guard_map", | ||
reason = "recently added, needs RFC for stabilization", | ||
issue = "0")] |
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.
An issue should be opened and these numbers updated before this lands.
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're going to fold this into #27746 so that's the issue number to use here.
Added the issue number and fixed the failing doctests, hopefully passes this time. |
64aeb56
to
6803736
Compare
@@ -231,7 +231,7 @@ impl<T: ?Sized> Mutex<T> { | |||
#[stable(feature = "rust1", since = "1.0.0")] | |||
pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> { | |||
if unsafe { self.inner.lock.try_lock() } { | |||
Ok(try!(MutexGuard::new(&*self.inner, &self.data))) | |||
Ok(try!(unsafe { MutexGuard::new(&*self.inner, &self.data) })) |
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.
With this new proliferation of unsafe
blocks, can blocks like this just be merged with the one above? (e.g. have one surrounding block)
6803736
to
4f61979
Compare
@alexcrichton updated for style changes both in mutex and rwlock |
4f61979
to
7292fbc
Compare
@@ -178,7 +178,7 @@ impl<T: ?Sized> RwLock<T> { | |||
#[stable(feature = "rust1", since = "1.0.0")] | |||
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> { | |||
unsafe { self.inner.lock.read() } | |||
RwLockReadGuard::new(&*self.inner, &self.data) | |||
unsafe { RwLockReadGuard::new(&*self.inner, &self.data) } |
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.
Ah looks like the rwlock here needs similar treatment as a mutex
7292fbc
to
fc875b0
Compare
How would we feel about also adding EDIT: Also updated for last nits. |
In theory we're slating Thanks! |
This is very useful when the RwLock is synchronizing access to a data structure and you would like to return or store guards which contain references to data inside the data structure instead of the data structure itself.
@alexcrichton damn, I've discovered a safety hole in |
This is not a problem with the |
It would be possible to provide a similar, but safe, API by defining a separate type for "mapped" mutex guards that can't be used with a |
Nice catch @reem! Certainly an interesting interaction between the two APIs... |
This is very useful when the RwLock is synchronizing access to a data
structure and you would like to return or store guards which contain
references to data inside the data structure instead of the data structure
itself.