// [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html)
let old_size = self.inner().strong.fetch_add(1, Relaxed);
- // However we need to guard against massive refcounts in case someone
- // is `mem::forget`ing Arcs. If we don't do this the count can overflow
- // and users will use-after free. We racily saturate to `isize::MAX` on
- // the assumption that there aren't ~2 billion threads incrementing
- // the reference count at once. This branch will never be taken in
- // any realistic program.
+ // However we need to guard against massive refcounts in case someone is `mem::forget`ing
+ // Arcs. If we don't do this the count can overflow and users will use-after free. This
+ // branch will never be taken in any realistic program. We abort because such a program is
+ // incredibly degenerate, and we don't care to support it.
//
- // We abort because such a program is incredibly degenerate, and we
- // don't care to support it.
+ // This check is not 100% water-proof: we error when the refcount grows beyond `isize::MAX`.
+ // But we do that check *after* having done the increment, so there is a chance here that
+ // the worst already happened and we actually do overflow the `usize` counter. However, that
+ // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment
+ // above and the `abort` below, which seems exceedingly unlikely.
if old_size > MAX_REFCOUNT {
abort();
}
}
impl Arc<dyn Any + Send + Sync> {
- #[inline]
- #[stable(feature = "rc_downcast", since = "1.29.0")]
/// Attempt to downcast the `Arc<dyn Any + Send + Sync>` to a concrete type.
///
/// # Examples
/// print_if_string(Arc::new(my_string));
/// print_if_string(Arc::new(0i8));
/// ```
+ #[inline]
+ #[stable(feature = "rc_downcast", since = "1.29.0")]
pub fn downcast<T>(self) -> Result<Arc<T>, Self>
where
- T: Any + Send + Sync + 'static,
+ T: Any + Send + Sync,
{
if (*self).is::<T>() {
unsafe {
Err(self)
}
}
+
+ /// Downcasts the `Arc<dyn Any + Send + Sync>` to a concrete type.
+ ///
+ /// For a safe alternative see [`downcast`].
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(downcast_unchecked)]
+ ///
+ /// use std::any::Any;
+ /// use std::sync::Arc;
+ ///
+ /// let x: Arc<dyn Any + Send + Sync> = Arc::new(1_usize);
+ ///
+ /// unsafe {
+ /// assert_eq!(*x.downcast_unchecked::<usize>(), 1);
+ /// }
+ /// ```
+ ///
+ /// # Safety
+ ///
+ /// The contained value must be of type `T`. Calling this method
+ /// with the incorrect type is *undefined behavior*.
+ ///
+ ///
+ /// [`downcast`]: Self::downcast
+ #[inline]
+ #[unstable(feature = "downcast_unchecked", issue = "90850")]
+ pub unsafe fn downcast_unchecked<T>(self) -> Arc<T>
+ where
+ T: Any + Send + Sync,
+ {
+ unsafe {
+ let ptr = self.ptr.cast::<ArcInner<T>>();
+ mem::forget(self);
+ Arc::from_inner(ptr)
+ }
+ }
}
impl<T> Weak<T> {