-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Extended Rc uniqueness methods #14908
Conversation
/// count is 1 (this pointer is unique). | ||
#[inline] | ||
#[experimental] | ||
pub fn maybe_unique<'a>(&'a self) -> Option<&'a mut T> { |
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.
This isn't safe because aliasing references can be created before or after calling maybe_unique
. It would need to take &'a mut self
and it would also need to prevent doing this if any Weak<T>
reference exists because it could be upgraded. There have been implementations of this before and I think the previously proposed approaches need to be considered too.
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.
Thank you, fixed now.
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.
Please note that maybe_unique does check for weak()
count to be 1
.
I'd suggest rewriting |
Thanks @eddyb. It's fixed now. I was hesitating to do that because |
// additional reference of either kind. | ||
if self.strong() != 1 || self.weak() != 1 { | ||
*self = Rc::new(self.deref().clone()) | ||
if self.maybe_unique().is_none() { |
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.
This is not what I meant. You should be able to match on the result of maybe_unique
.
(though, in retrospective, I may have underestimated the complexity of this change)
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.
That's what I initially tried, but Rust doesn't allow reassigning *self
in the the match arm of maybe_unique()
because the latter freezes self.
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.
You have to return early in the other branch and mutate outside of the match
.
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.
Reverted make_unique()
back to the original implementation after a brief discussion with @eddyb. The unsafe{}
can be replaced by 2 calls to maybe_unique(), but that may not be as efficient.
@kvark I think I understand the use-case for Can you spell out how |
@aturon Thanks for having a look at this PR. I don't have a |
These should not be methods on The current state of my PR #15399 actually provides the same functionality under different names, along with a 3rd function to unwrap a uniquely-owned If you have no objection, I'm inclined to re-submit just that one commit as a PR (that would obsolete this PR). |
@kballard Thanks, I trust you to take care of this. Besides, I'm long past the point where I needed it. |
maybe_unique()
allows to mutate the referenced data if the pointer is guaranteed to be the only one.is_last_standing()
allows to check if this pointer is the last strong one.One possible application of these methods is a shared resource factory. The resource doesn't know how it is built or destroyed, it may even be method-less. The factory knows how to create a resource and how to destroy it. Upon creation, the factory stores
Rc<T>
internally and returns a cloned reference. Later, at a designated (by the user) moment, the factory can sweep over known references and delete only those resources that are no longer needed by anyone else (here comesmaybe_unique
oris_last_standing
).