summary refs log tree commit diff
path: root/src/liballoc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-07-21 04:49:00 +0000
committerbors <bors@rust-lang.org>2017-07-21 04:49:00 +0000
commitd361efac2639fa9dd7f6195e4276a728b8875d7a (patch)
tree30994df2e955eb884b436abbbbc07760e0668818 /src/liballoc
parente3c8433ebb4a1acf125cae34ebd910869c894ebd (diff)
parent8416713240e11e898872f5028f927997f3754696 (diff)
downloadrust-d361efac2639fa9dd7f6195e4276a728b8875d7a.tar.gz
rust-d361efac2639fa9dd7f6195e4276a728b8875d7a.zip
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.
Diffstat (limited to 'src/liballoc')
-rw-r--r--src/liballoc/arc.rs24
1 files changed, 23 insertions, 1 deletions
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index d9edf50b9c8..85c7efb7ac5 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -453,7 +453,10 @@ impl<T: ?Sized> Arc<T> {
     #[inline]
     #[stable(feature = "arc_counts", since = "1.15.0")]
     pub fn weak_count(this: &Self) -> usize {
-        this.inner().weak.load(SeqCst) - 1
+        let cnt = this.inner().weak.load(SeqCst);
+        // If the weak count is currently locked, the value of the
+        // count was 0 just before taking the lock.
+        if cnt == usize::MAX { 0 } else { cnt - 1 }
     }
 
     /// Gets the number of strong (`Arc`) pointers to this value.
@@ -1498,6 +1501,25 @@ mod tests {
         assert!(Arc::ptr_eq(&five, &same_five));
         assert!(!Arc::ptr_eq(&five, &other_five));
     }
+
+    #[test]
+    #[cfg_attr(target_os = "emscripten", ignore)]
+    fn test_weak_count_locked() {
+        let mut a = Arc::new(atomic::AtomicBool::new(false));
+        let a2 = a.clone();
+        let t = thread::spawn(move || {
+            for _i in 0..1000000 {
+                Arc::get_mut(&mut a);
+            }
+            a.store(true, SeqCst);
+        });
+
+        while !a2.load(SeqCst) {
+            let n = Arc::weak_count(&a2);
+            assert!(n < 2, "bad weak count: {}", n);
+        }
+        t.join().unwrap();
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]