Skip to content

Commit 2fe3b3b

Browse files
Implement Weak::{strong_count, weak_count}
1 parent 7425663 commit 2fe3b3b

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/liballoc/rc.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,40 @@ impl<T: ?Sized> Weak<T> {
12841284
}
12851285
}
12861286

1287+
/// Gets the number of strong (`Rc`) pointers pointing to this value.
1288+
///
1289+
/// If `self` was created using [`Weak::new`], this will return 0.
1290+
///
1291+
/// [`Weak::new`]: #method.new
1292+
#[unstable(feature = "weak_counts", issue = "0")]
1293+
pub fn strong_count(&self) -> usize {
1294+
if let Some(inner) = self.inner() {
1295+
inner.strong()
1296+
} else {
1297+
0
1298+
}
1299+
}
1300+
1301+
/// Gets the number of `Weak` pointers pointing to this value.
1302+
///
1303+
/// If `self` was created using [`Weak::new`], this will return 0. If not,
1304+
/// the returned value is at least 1, since `self` still points to the
1305+
/// value.
1306+
///
1307+
/// [`Weak::new`]: #method.new
1308+
#[unstable(feature = "weak_counts", issue = "0")]
1309+
pub fn weak_count(&self) -> usize {
1310+
if let Some(inner) = self.inner() {
1311+
if inner.strong() > 0 {
1312+
inner.weak() - 1 // subtract the implicit weak ptr
1313+
} else {
1314+
inner.weak()
1315+
}
1316+
} else {
1317+
0
1318+
}
1319+
}
1320+
12871321
/// Return `None` when the pointer is dangling and there is no allocated `RcBox`,
12881322
/// i.e., this `Weak` was created by `Weak::new`
12891323
#[inline]
@@ -1622,6 +1656,33 @@ mod tests {
16221656
drop(c);
16231657
}
16241658

1659+
#[test]
1660+
fn weak_counts() {
1661+
assert_eq!(Weak::weak_count(&Weak::<u64>::new()), 0);
1662+
assert_eq!(Weak::strong_count(&Weak::<u64>::new()), 0);
1663+
1664+
let a = Rc::new(0);
1665+
let w = Rc::downgrade(&a);
1666+
assert_eq!(Weak::strong_count(&w), 1);
1667+
assert_eq!(Weak::weak_count(&w), 1);
1668+
let w2 = w.clone();
1669+
assert_eq!(Weak::strong_count(&w), 1);
1670+
assert_eq!(Weak::weak_count(&w), 2);
1671+
assert_eq!(Weak::strong_count(&w2), 1);
1672+
assert_eq!(Weak::weak_count(&w2), 2);
1673+
drop(w);
1674+
assert_eq!(Weak::strong_count(&w2), 1);
1675+
assert_eq!(Weak::weak_count(&w2), 1);
1676+
let a2 = a.clone();
1677+
assert_eq!(Weak::strong_count(&w2), 2);
1678+
assert_eq!(Weak::weak_count(&w2), 1);
1679+
drop(a2);
1680+
drop(a);
1681+
assert_eq!(Weak::strong_count(&w2), 0);
1682+
assert_eq!(Weak::weak_count(&w2), 1);
1683+
drop(w2);
1684+
}
1685+
16251686
#[test]
16261687
fn try_unwrap() {
16271688
let x = Rc::new(3);

src/liballoc/sync.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,25 @@ impl<T: ?Sized> Weak<T> {
11171117
}
11181118
}
11191119

1120+
/// Gets the number of strong (`Arc`) pointers pointing to this value.
1121+
///
1122+
/// If `self` was created using [`Weak::new`], this will return 0.
1123+
///
1124+
/// [`Weak::new`]: #method.new
1125+
#[unstable(feature = "weak_counts", issue = "0")]
1126+
pub fn strong_count(&self) -> usize {
1127+
if let Some(inner) = self.inner() {
1128+
inner.strong.load(SeqCst)
1129+
} else {
1130+
0
1131+
}
1132+
}
1133+
1134+
// Due to the implicit weak pointer added when any strong pointers are
1135+
// around, we cannot implement `weak_count` correctly since it necessarily
1136+
// requires accessing the strong count and weak count in an unsynchronized
1137+
// fashion.
1138+
11201139
/// Return `None` when the pointer is dangling and there is no allocated `ArcInner`,
11211140
/// i.e., this `Weak` was created by `Weak::new`
11221141
#[inline]

0 commit comments

Comments
 (0)