Make weak_count return an Option<usize>
This commit is contained in:
parent
7e0edb39ba
commit
b664341d91
2 changed files with 22 additions and 26 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue