Skip to content
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

std::sync::Weak::strong_count #50158

Closed
SoniEx2 opened this issue Apr 22, 2018 · 10 comments
Closed

std::sync::Weak::strong_count #50158

SoniEx2 opened this issue Apr 22, 2018 · 10 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@SoniEx2
Copy link
Contributor

SoniEx2 commented Apr 22, 2018

I'd like to test if a Weak is done for without potentially incrementing an atomic refcount, because doing so is slow.

I want a faster alternative to Weak.upgrade().is_some().

also currently have this in my code: https://play.rust-lang.org/?gist=339c2c518a2d42aee7e5a585133427eb&version=stable

// since Weaks are completely useless...
// this checks if the arc and weak point to the same value without attempting to upgrade the weak.
// this is "safer" than trying to get the strong count
fn compare_arc_weak<T>(arc: &Arc<T>, weak: &Weak<T>) -> bool {
    unsafe {
        // we assume arc and weak have same size and alignment as usize
        let arcusize: usize = mem::transmute_copy(arc);
        let weakusize: usize = mem::transmute_copy(weak);
        arcusize == weakusize
    }
}
@ishitatsuyuki
Copy link
Contributor

Relying on such count is racy. You have to upgrade to ensure thread safety.

@SoniEx2
Copy link
Contributor Author

SoniEx2 commented Apr 23, 2018

You absolutely do not.

If the strong count is 0(?), then the weak is done for, and upgrade is always gonna be None.

(Altho tbh after some more tweaking I ended up not needing the strong count. Still needed that compare_arc_weak function tho.)

@ishitatsuyuki
Copy link
Contributor

The race is well known, and what you proposed should never be a part of public API.

Identity equality is another thing. We currently doesn't expose those which need discussion on how to add them.

@SoniEx2
Copy link
Contributor Author

SoniEx2 commented Apr 23, 2018

You can't get the strong count back up once it reaches 0. That's the whole point of Arc/Weak! Because once it's 0, it's dropped.

Unless you're saying there's a race condition in which you can turn a Weak into an uninitialized/dropped Arc!?

@ishitatsuyuki
Copy link
Contributor

Well, that particular thing is correct.

However, with regards to this issue,

  1. Obtaining the count directly encourage racy behaviour
  2. The motivation is not clear.

@oli-obk
Copy link
Contributor

oli-obk commented Apr 23, 2018

Do you have an example of using the comparison? I'm curious about the use case

@Lymia
Copy link
Contributor

Lymia commented Apr 25, 2018

rust/src/liballoc/rc.rs

Lines 1228 to 1236 in e028687

#[stable(feature = "rc_weak", since = "1.4.0")]
pub fn upgrade(&self) -> Option<Rc<T>> {
if self.strong() == 0 {
None
} else {
self.inc_strong();
Some(Rc { ptr: self.ptr, phantom: PhantomData })
}
}

This function is factually unnecessary for this use case, as Weak::upgrade already performs this check.

@SoniEx2
Copy link
Contributor Author

SoniEx2 commented Apr 25, 2018

You're looking at the wrong Weak. Check the arc Weak, it's more expensive.

@RalfJung
Copy link
Member

The question still stands: When do you ever think it is useful to know that, at some point in the past, the Weak was (not) valid? This is the best you can get.
It is true that once the Weak is invalid, it will stay invalid, but how is that useful information?

@SoniEx2
Copy link
Contributor Author

SoniEx2 commented Aug 15, 2018

I have no idea what exactly I was using it for, but I just want to be able to use "stupid" optimizations like compare Arc and Weak (which doesn't need to be an atomic operation) to avoid an atomic operation/refcount/optimize for inequality.

I think the usual use-case would involve checking if they're (not) the same and upgrading/cloning as needed.

(I feel like this might have something to do with an eventbus thing I was working on but idk)

@XAMPPRocky XAMPPRocky added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Sep 25, 2018
bors added a commit that referenced this issue Jan 31, 2019
Implement Weak::{strong_count, weak_count}

The counters are also useful on `Weak`, not just on strong references (`Rc` or `Arc`).

In situations where there are still strong references around, you can also get these counts by temporarily upgrading and adjusting the values accordingly. Using the methods introduced here is simpler to do, less error-prone (since you can't forget to adjust the counts), can also be used when no strong references are around anymore, and might be more efficient due to not having to temporarily create an `Rc`.

This is mainly useful in assertions or tests of complex data structures. Data structures might have internal invariants that make them the sole owner of a `Weak` pointer, and an assertion on the weak count could be used to ensure that this indeed happens as expected. Due to the presence of `Weak::upgrade`, the `strong_count` becomes less useful, but it still seems worthwhile to mirror the API of `Rc`.

TODO:
* [X] Tracking issue - #57977

Closes #50158
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants