1
Fork 0

Make weak_count return an Option<usize>

This commit is contained in:
Jonas Schievink 2019-01-29 21:58:17 +01:00
commit b664341d91
2 changed files with 22 additions and 26 deletions

View file

@ -1300,22 +1300,20 @@ impl<T: ?Sized> Weak<T> {
/// Gets the number of `Weak` pointers pointing to this value. /// Gets the number of `Weak` pointers pointing to this value.
/// ///
/// If `self` was created using [`Weak::new`], this will return 0. If not, /// If `self` was created using [`Weak::new`], this will return `None`. If
/// the returned value is at least 1, since `self` still points to the /// not, the returned value is at least 1, since `self` still points to the
/// value. /// value.
/// ///
/// [`Weak::new`]: #method.new /// [`Weak::new`]: #method.new
#[unstable(feature = "weak_counts", issue = "0")] #[unstable(feature = "weak_counts", issue = "0")]
pub fn weak_count(&self) -> usize { pub fn weak_count(&self) -> Option<usize> {
if let Some(inner) = self.inner() { self.inner().map(|inner| {
if inner.strong() > 0 { if inner.strong() > 0 {
inner.weak() - 1 // subtract the implicit weak ptr inner.weak() - 1 // subtract the implicit weak ptr
} else { } else {
inner.weak() inner.weak()
} }
} else { })
0
}
} }
/// Return `None` when the pointer is dangling and there is no allocated `RcBox`, /// Return `None` when the pointer is dangling and there is no allocated `RcBox`,
@ -1658,28 +1656,28 @@ mod tests {
#[test] #[test]
fn weak_counts() { fn weak_counts() {
assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0); assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None);
assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0);
let a = Rc::new(0); let a = Rc::new(0);
let w = Rc::downgrade(&a); let w = Rc::downgrade(&a);
assert_eq!(Weak::strong_count(&w), 1); assert_eq!(Weak::strong_count(&w), 1);
assert_eq!(Weak::weak_count(&w), 1); assert_eq!(Weak::weak_count(&w), Some(1));
let w2 = w.clone(); let w2 = w.clone();
assert_eq!(Weak::strong_count(&w), 1); assert_eq!(Weak::strong_count(&w), 1);
assert_eq!(Weak::weak_count(&w), 2); assert_eq!(Weak::weak_count(&w), Some(2));
assert_eq!(Weak::strong_count(&w2), 1); assert_eq!(Weak::strong_count(&w2), 1);
assert_eq!(Weak::weak_count(&w2), 2); assert_eq!(Weak::weak_count(&w2), Some(2));
drop(w); drop(w);
assert_eq!(Weak::strong_count(&w2), 1); assert_eq!(Weak::strong_count(&w2), 1);
assert_eq!(Weak::weak_count(&w2), 1); assert_eq!(Weak::weak_count(&w2), Some(1));
let a2 = a.clone(); let a2 = a.clone();
assert_eq!(Weak::strong_count(&w2), 2); assert_eq!(Weak::strong_count(&w2), 2);
assert_eq!(Weak::weak_count(&w2), 1); assert_eq!(Weak::weak_count(&w2), Some(1));
drop(a2); drop(a2);
drop(a); drop(a);
assert_eq!(Weak::strong_count(&w2), 0); assert_eq!(Weak::strong_count(&w2), 0);
assert_eq!(Weak::weak_count(&w2), 1); assert_eq!(Weak::weak_count(&w2), Some(1));
drop(w2); drop(w2);
} }

View file

@ -1146,12 +1146,12 @@ impl<T: ?Sized> Weak<T> {
/// ///
/// [`Weak::new`]: #method.new /// [`Weak::new`]: #method.new
#[unstable(feature = "weak_counts", issue = "0")] #[unstable(feature = "weak_counts", issue = "0")]
pub fn weak_count(&self) -> usize { pub fn weak_count(&self) -> Option<usize> {
// Due to the implicit weak pointer added when any strong pointers are // Due to the implicit weak pointer added when any strong pointers are
// around, we cannot implement `weak_count` correctly since it // around, we cannot implement `weak_count` correctly since it
// necessarily requires accessing the strong count and weak count in an // necessarily requires accessing the strong count and weak count in an
// unsynchronized fashion. So this version is a bit racy. // unsynchronized fashion. So this version is a bit racy.
if let Some(inner) = self.inner() { self.inner().map(|inner| {
let strong = inner.strong.load(SeqCst); let strong = inner.strong.load(SeqCst);
let weak = inner.weak.load(SeqCst); let weak = inner.weak.load(SeqCst);
if strong == 0 { if strong == 0 {
@ -1169,9 +1169,7 @@ impl<T: ?Sized> Weak<T> {
// pointer), we guard against that specifically. // pointer), we guard against that specifically.
cmp::max(1, weak - 1) cmp::max(1, weak - 1)
} }
} else { })
0
}
} }
/// Return `None` when the pointer is dangling and there is no allocated `ArcInner`, /// Return `None` when the pointer is dangling and there is no allocated `ArcInner`,
@ -1695,28 +1693,28 @@ mod tests {
#[test] #[test]
fn weak_counts() { fn weak_counts() {
assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0); assert_eq!(Weak::weak_count(&Weak::<u64>::new()), None);
assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0); assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0);
let a = Arc::new(0); let a = Arc::new(0);
let w = Arc::downgrade(&a); let w = Arc::downgrade(&a);
assert_eq!(Weak::strong_count(&w), 1); assert_eq!(Weak::strong_count(&w), 1);
assert_eq!(Weak::weak_count(&w), 1); assert_eq!(Weak::weak_count(&w), Some(1));
let w2 = w.clone(); let w2 = w.clone();
assert_eq!(Weak::strong_count(&w), 1); assert_eq!(Weak::strong_count(&w), 1);
assert_eq!(Weak::weak_count(&w), 2); assert_eq!(Weak::weak_count(&w), Some(2));
assert_eq!(Weak::strong_count(&w2), 1); assert_eq!(Weak::strong_count(&w2), 1);
assert_eq!(Weak::weak_count(&w2), 2); assert_eq!(Weak::weak_count(&w2), Some(2));
drop(w); drop(w);
assert_eq!(Weak::strong_count(&w2), 1); assert_eq!(Weak::strong_count(&w2), 1);
assert_eq!(Weak::weak_count(&w2), 1); assert_eq!(Weak::weak_count(&w2), Some(1));
let a2 = a.clone(); let a2 = a.clone();
assert_eq!(Weak::strong_count(&w2), 2); assert_eq!(Weak::strong_count(&w2), 2);
assert_eq!(Weak::weak_count(&w2), 1); assert_eq!(Weak::weak_count(&w2), Some(1));
drop(a2); drop(a2);
drop(a); drop(a);
assert_eq!(Weak::strong_count(&w2), 0); assert_eq!(Weak::strong_count(&w2), 0);
assert_eq!(Weak::weak_count(&w2), 1); assert_eq!(Weak::weak_count(&w2), Some(1));
drop(w2); drop(w2);
} }