summaryrefslogtreecommitdiffstats
path: root/library/alloc/src/sync.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/alloc/src/sync.rs')
-rw-r--r--library/alloc/src/sync.rs61
1 files changed, 31 insertions, 30 deletions
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 4377edeee..81cd77074 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -3,6 +3,10 @@
//! Thread-safe reference-counting pointers.
//!
//! See the [`Arc<T>`][Arc] documentation for more details.
+//!
+//! **Note**: This module is only available on platforms that support atomic
+//! loads and stores of pointers. This may be detected at compile time using
+//! `#[cfg(target_has_atomic = "ptr")]`.
use core::any::Any;
use core::borrow;
@@ -82,6 +86,11 @@ macro_rules! acquire {
/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic]
/// types.
///
+/// **Note**: This type is only available on platforms that support atomic
+/// loads and stores of pointers, which includes all platforms that support
+/// the `std` crate but not all those which only support [`alloc`](crate).
+/// This may be detected at compile time using `#[cfg(target_has_atomic = "ptr")]`.
+///
/// ## Thread Safety
///
/// Unlike [`Rc<T>`], `Arc<T>` uses atomic operations for its reference
@@ -1108,8 +1117,8 @@ impl<T: ?Sized> Arc<T> {
drop(Weak { ptr: self.ptr });
}
- /// Returns `true` if the two `Arc`s point to the same allocation
- /// (in a vein similar to [`ptr::eq`]).
+ /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to
+ /// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
///
/// # Examples
///
@@ -1195,7 +1204,7 @@ impl<T: ?Sized> Arc<T> {
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
- |mem| mem.with_metadata_of(ptr as *mut ArcInner<T>),
+ |mem| mem.with_metadata_of(ptr as *const ArcInner<T>),
)
}
}
@@ -1980,33 +1989,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.
@@ -2067,9 +2069,9 @@ impl<T: ?Sized> Weak<T> {
}
}
- /// Returns `true` if the two `Weak`s point to the same allocation (similar to
- /// [`ptr::eq`]), or if both don't point to any allocation
- /// (because they were created with `Weak::new()`).
+ /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if
+ /// both don't point to any allocation (because they were created with `Weak::new()`). See [that
+ /// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
///
/// # Notes
///
@@ -2764,7 +2766,6 @@ fn data_offset_align(align: usize) -> usize {
layout.size() + layout.padding_needed_for(align)
}
-#[cfg(not(bootstrap))]
#[stable(feature = "arc_error", since = "1.52.0")]
impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
#[allow(deprecated, deprecated_in_future)]