diff options
| author | Jonas Schievink <jonasschievink@gmail.com> | 2018-12-11 00:40:39 +0100 |
|---|---|---|
| committer | Jonas Schievink <jonasschievink@gmail.com> | 2019-01-29 21:07:35 +0100 |
| commit | 2fe3b3b486b3b5e1ec1e6ad259d8840b88b7c77a (patch) | |
| tree | a76eb8020a512e355281b1932ac36557cfc0ff62 /src/liballoc | |
| parent | 74256630117fedf479edbd1145cac47c88036aec (diff) | |
Implement Weak::{strong_count, weak_count}
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/rc.rs | 61 | ||||
| -rw-r--r-- | src/liballoc/sync.rs | 19 |
2 files changed, 80 insertions, 0 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index c0dc010fe59..7ee05eaff91 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1284,6 +1284,40 @@ impl<T: ?Sized> Weak<T> { } } + /// Gets the number of strong (`Rc`) pointers pointing to this value. + /// + /// If `self` was created using [`Weak::new`], this will return 0. + /// + /// [`Weak::new`]: #method.new + #[unstable(feature = "weak_counts", issue = "0")] + pub fn strong_count(&self) -> usize { + if let Some(inner) = self.inner() { + inner.strong() + } else { + 0 + } + } + + /// Gets the number of `Weak` pointers pointing to this value. + /// + /// If `self` was created using [`Weak::new`], this will return 0. If not, + /// the returned value is at least 1, since `self` still points to the + /// value. + /// + /// [`Weak::new`]: #method.new + #[unstable(feature = "weak_counts", issue = "0")] + pub fn weak_count(&self) -> usize { + if let Some(inner) = self.inner() { + if inner.strong() > 0 { + inner.weak() - 1 // subtract the implicit weak ptr + } else { + inner.weak() + } + } else { + 0 + } + } + /// Return `None` when the pointer is dangling and there is no allocated `RcBox`, /// i.e., this `Weak` was created by `Weak::new` #[inline] @@ -1623,6 +1657,33 @@ mod tests { } #[test] + fn weak_counts() { + assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0); + assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); + + let a = Rc::new(0); + let w = Rc::downgrade(&a); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 1); + let w2 = w.clone(); + assert_eq!(Weak::strong_count(&w), 1); + assert_eq!(Weak::weak_count(&w), 2); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 2); + drop(w); + assert_eq!(Weak::strong_count(&w2), 1); + assert_eq!(Weak::weak_count(&w2), 1); + let a2 = a.clone(); + assert_eq!(Weak::strong_count(&w2), 2); + assert_eq!(Weak::weak_count(&w2), 1); + drop(a2); + drop(a); + assert_eq!(Weak::strong_count(&w2), 0); + assert_eq!(Weak::weak_count(&w2), 1); + drop(w2); + } + + #[test] fn try_unwrap() { let x = Rc::new(3); assert_eq!(Rc::try_unwrap(x), Ok(3)); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 390a0791650..fd3519dee18 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1117,6 +1117,25 @@ impl<T: ?Sized> Weak<T> { } } + /// Gets the number of strong (`Arc`) pointers pointing to this value. + /// + /// If `self` was created using [`Weak::new`], this will return 0. + /// + /// [`Weak::new`]: #method.new + #[unstable(feature = "weak_counts", issue = "0")] + pub fn strong_count(&self) -> usize { + if let Some(inner) = self.inner() { + inner.strong.load(SeqCst) + } else { + 0 + } + } + + // Due to the implicit weak pointer added when any strong pointers are + // around, we cannot implement `weak_count` correctly since it necessarily + // requires accessing the strong count and weak count in an unsynchronized + // fashion. + /// Return `None` when the pointer is dangling and there is no allocated `ArcInner`, /// i.e., this `Weak` was created by `Weak::new` #[inline] |
