-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Rework Rc and Arc APIs for FCP #27837
Conversation
#[unstable(feature = "rc_unique", reason = "needs FCP", issue = "27718")] | ||
pub fn make_mut(this: &mut Self) -> &mut T { | ||
if !Rc::is_unique(this) { | ||
*this = Rc::new((**this).clone()) |
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 calls clone() in some cases where it isn't necessary.
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.
Can you elaborate?
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.
In the case where self is the only strong pointer, but there are other weak pointers, you can just ptr::read the value out of the old Rc.
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.
If there's only one strong pointer (this one) but many weak pointers then you can move ownership from the original Rc
to a new one, thereby destroying the original one (decrementing its strong count to 0).
I believe Arc
takes this strategy currently.
9c3cf0c
to
86bbc3d
Compare
*self = Rc::new((**self).clone()) | ||
#[unstable(feature = "rc_unique", reason = "needs FCP", issue = "27718")] | ||
pub fn make_mut(this: &mut Self) -> &mut T { | ||
if Rc::strong_count(this) != 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.
Shouldn’t this be 1 rather than 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.
god damnit
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 should probably focus on this patch at all
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.
Pleased to announce the tests caught this
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.
Good tests :)
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.
Err, no they didn't, try_unwrap just had an out of date test.
This is actually technically correct. Just weird to say. (The check is really > 1, where 0 is a nonsense value) -- it's needlessly ineffecient though.
ebd3c6e
to
777dd7c
Compare
☔ The latest upstream changes (presumably #27818) made this pull request unmergeable. Please resolve the merge conflicts. |
Just out of curiosity, why is it preferable to have |
@glaebhoerl when working with |
#[unstable(feature = "arc_unique", reason = "needs FCP", issue = "27718")] | ||
pub fn try_unwrap(this: Self) -> Result<T, Self> { | ||
// See `drop` for why all these atomics are like this | ||
if this.inner().strong.compare_and_swap(1, 0, Release) != 1 { return Err(this) } |
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 believe this can be replaced with an Acquire
on the CAS and no fence, because this operation will only succeed if we're the last one out. (Similar to what we do for make_mut
.)
- Normally we fence after only if we see we're the last one, but doing the
Acquire
as part of the operation is slightly more efficient in some architectures. - Since this only succeeds if we're the last strong ref, the
Release
isn't needed; there's no one who would do a correspondingAcquire
.
(That said, this is fine as-is; you could treat these as optimizations to be done later.)
Hey, sorry for the delay reviewing this. Overall, this seems like a pretty good direction for the API (e.g.,
Anyway, basically, r=me. |
📌 Commit 9a0db5b has been approved by |
* Add `Rc::would_unwrap(&Self) -> bool` to introspect whether try_unwrap would succeed, because it's destructive (unlike get_mut). * Move `rc.downgrade()` to `Rc::downgrade(&Self)` per conventions. * Deprecate `Rc::weak_count` and `Rc::strong_count` for questionable utility. * Deprecate `Rc::is_unique` for questionable semantics (there are two kinds of uniqueness with Weak pointers in play). * Rename `rc.make_unique()` to `Rc::make_mut(&mut Self)` per conventions, to avoid uniqueness terminology, and to clarify the relation to `Rc::get_mut`.
* Add previously omitted function `Arc::try_unwrap(Self) -> Result<T, Self>` * Move `arc.downgrade()` to `Arc::downgrade(&Self)` per conventions. * Deprecate `Arc::weak_count` and `Arc::strong_count` for raciness. It is almost impossible to correctly act on these results without a CAS loop on the actual fields. * Rename `Arc::make_unique` to `Arc::make_mut` to avoid uniqueness terminology and to clarify relation to `Arc::get_mut`.
@bors r=aturon (rebasing error) |
📌 Commit 4c8d75f has been approved by |
That reminds me, do the docs mention the |
@SimonSapin Nope, definitely a good follow up. |
This prepares both for the FCP of #27718 Arc: * Add previously omitted function `Arc::try_unwrap(Self) -> Result<T, Self>` * Move `arc.downgrade()` to `Arc::downgrade(&Self)` per conventions. * Deprecate `Arc::weak_count` and `Arc::strong_count` for raciness. It is almost impossible to correctly act on these results without a CAS loop on the actual fields. * Rename `Arc::make_unique` to `Arc::make_mut` to avoid uniqueness terminology and to clarify relation to `Arc::get_mut`. Rc: * Add `Rc::would_unwrap(&Self) -> bool` to introspect whether try_unwrap would succeed, because it's destructive (unlike get_mut). * Move `rc.downgrade()` to `Rc::downgrade(&Self)` per conventions. * Deprecate `Rc::weak_count` and `Rc::strong_count` for questionable utility. * Deprecate `Rc::is_unique` for questionable semantics (there are two kinds of uniqueness with Weak pointers in play). * Rename `rc.make_unique()` to `Rc::make_mut(&mut Self)` per conventions, to avoid uniqueness terminology, and to clarify the relation to `Rc::get_mut`. Notable omission: * Arc::would_unwrap is not added due to the fact that it's racy, and therefore doesn't provide much actionable information. (note: rc_would_unwrap is not proposed for FCP as it is truly experimental) r? @aturon (careful attention needs to be taken for the new Arc::try_unwrap, but intuitively it should "just work" by virtue of being semantically equivalent to Drop).
Hm looks like our android slave never came back after I tried last time, but this passed all tests otherwise so merging manually |
This prepares both for the FCP of #27718
Arc:
Arc::try_unwrap(Self) -> Result<T, Self>
arc.downgrade()
toArc::downgrade(&Self)
per conventions.Arc::weak_count
andArc::strong_count
for raciness. It is almostimpossible to correctly act on these results without a CAS loop on the actual
fields.
Arc::make_unique
toArc::make_mut
to avoid uniqueness terminologyand to clarify relation to
Arc::get_mut
.Rc:
Rc::would_unwrap(&Self) -> bool
to introspect whether try_unwrap would succeed,because it's destructive (unlike get_mut).
rc.downgrade()
toRc::downgrade(&Self)
per conventions.Rc::weak_count
andRc::strong_count
for questionable utility.Rc::is_unique
for questionable semantics (there are two kinds ofuniqueness with Weak pointers in play).
rc.make_unique()
toRc::make_mut(&mut Self)
per conventions, toavoid uniqueness terminology, and to clarify the relation to
Rc::get_mut
.Notable omission:
provide much actionable information.
(note: rc_would_unwrap is not proposed for FCP as it is truly experimental)
r? @aturon (careful attention needs to be taken for the new Arc::try_unwrap, but intuitively it should "just work" by virtue of being semantically equivalent to Drop).