about summary refs log tree commit diff
path: root/library/alloc/src
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-10-02 20:42:21 +0530
committerGitHub <noreply@github.com>2022-10-02 20:42:21 +0530
commited9740846b8fc813a763778e792589c17b359b45 (patch)
treeb19f1358b1f4cb531a894f6295e5759df96949e8 /library/alloc/src
parent13f47f608e8e9fcdd60f64688e12f5f4c2f7c317 (diff)
parent80c8680a0c0d5b174744c2e56667808be21aeade (diff)
downloadrust-ed9740846b8fc813a763778e792589c17b359b45.tar.gz
rust-ed9740846b8fc813a763778e792589c17b359b45.zip
Rollup merge of #102098 - xfix:weak-upgrade-fetch-update, r=Mark-Simulacrum
Use fetch_update in sync::Weak::upgrade

Using `fetch_update` makes it more clear that it's CAS loop then manually implementing one.
Diffstat (limited to 'library/alloc/src')
-rw-r--r--library/alloc/src/sync.rs39
1 files changed, 16 insertions, 23 deletions
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index a5322953d49..d0e5b6f4d82 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1980,33 +1980,26 @@ impl<T: ?Sized> Weak<T> {
         // We use a CAS loop to increment the strong count instead of a
         // fetch_add as this function should never take the reference count
         // from zero to one.
-        let inner = self.inner()?;
-
-        // Relaxed load because any write of 0 that we can observe
-        // leaves the field in a permanently zero state (so a
-        // "stale" read of 0 is fine), and any other value is
-        // confirmed via the CAS below.
-        let mut n = inner.strong.load(Relaxed);
-
-        loop {
-            if n == 0 {
-                return None;
-            }
-
-            // See comments in `Arc::clone` for why we do this (for `mem::forget`).
-            if n > MAX_REFCOUNT {
-                abort();
-            }
-
+        self.inner()?
+            .strong
             // Relaxed is fine for the failure case because we don't have any expectations about the new state.
             // Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner
             // value can be initialized after `Weak` references have already been created. In that case, we
             // expect to observe the fully initialized value.
-            match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) {
-                Ok(_) => return Some(unsafe { Arc::from_inner(self.ptr) }), // null checked above
-                Err(old) => n = old,
-            }
-        }
+            .fetch_update(Acquire, Relaxed, |n| {
+                // Any write of 0 we can observe leaves the field in permanently zero state.
+                if n == 0 {
+                    return None;
+                }
+                // See comments in `Arc::clone` for why we do this (for `mem::forget`).
+                if n > MAX_REFCOUNT {
+                    abort();
+                }
+                Some(n + 1)
+            })
+            .ok()
+            // null checked above
+            .map(|_| unsafe { Arc::from_inner(self.ptr) })
     }
 
     /// Gets the number of strong (`Arc`) pointers pointing to this allocation.