Skip to content

Commit d361efa

Browse files
committed
Auto merge of #43318 - jhjourdan:jh/fix_weak_cound_MAX, r=alexcrichton
Fix in weak_count in Arc in the case the weak count is locked. In the case the weak count was locked, the weak_count function could return usize::MAX. We need to test this condition manually.
2 parents e3c8433 + 8416713 commit d361efa

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

src/liballoc/arc.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,10 @@ impl<T: ?Sized> Arc<T> {
453453
#[inline]
454454
#[stable(feature = "arc_counts", since = "1.15.0")]
455455
pub fn weak_count(this: &Self) -> usize {
456-
this.inner().weak.load(SeqCst) - 1
456+
let cnt = this.inner().weak.load(SeqCst);
457+
// If the weak count is currently locked, the value of the
458+
// count was 0 just before taking the lock.
459+
if cnt == usize::MAX { 0 } else { cnt - 1 }
457460
}
458461

459462
/// Gets the number of strong (`Arc`) pointers to this value.
@@ -1498,6 +1501,25 @@ mod tests {
14981501
assert!(Arc::ptr_eq(&five, &same_five));
14991502
assert!(!Arc::ptr_eq(&five, &other_five));
15001503
}
1504+
1505+
#[test]
1506+
#[cfg_attr(target_os = "emscripten", ignore)]
1507+
fn test_weak_count_locked() {
1508+
let mut a = Arc::new(atomic::AtomicBool::new(false));
1509+
let a2 = a.clone();
1510+
let t = thread::spawn(move || {
1511+
for _i in 0..1000000 {
1512+
Arc::get_mut(&mut a);
1513+
}
1514+
a.store(true, SeqCst);
1515+
});
1516+
1517+
while !a2.load(SeqCst) {
1518+
let n = Arc::weak_count(&a2);
1519+
assert!(n < 2, "bad weak count: {}", n);
1520+
}
1521+
t.join().unwrap();
1522+
}
15011523
}
15021524

15031525
#[stable(feature = "rust1", since = "1.0.0")]

0 commit comments

Comments
 (0)