/// Weak pointers will not keep the data inside of the `Arc` alive, and can be
/// used to break cycles between `Arc` pointers.
#[unsafe_no_drop_flag]
-#[unstable(feature = "arc_weak",
- reason = "Weak pointers may not belong in this module.",
- issue = "27718")]
+#[unstable(feature = "arc_weak", reason = "needs FCP", issue = "27718")]
pub struct Weak<T: ?Sized> {
// FIXME #12808: strange name to try to avoid interfering with
// field accesses of the contained type via Deref
// the value usize::MAX acts as a sentinel for temporarily "locking" the
// ability to upgrade weak pointers or downgrade strong ones; this is used
- // to avoid races in `make_unique` and `get_mut`.
+ // to avoid races in `make_mut` and `get_mut`.
weak: atomic::AtomicUsize,
data: T,
};
Arc { _ptr: unsafe { NonZero::new(Box::into_raw(x)) } }
}
+
+ /// Unwraps the contained value if the `Arc<T>` has only one strong reference.
+ /// This will succeed even if there are outstanding weak references.
+ ///
+ /// Otherwise, an `Err` is returned with the same `Arc<T>`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(arc_unique)]
+ /// use std::sync::Arc;
+ ///
+ /// let x = Arc::new(3);
+ /// assert_eq!(Arc::try_unwrap(x), Ok(3));
+ ///
+ /// let x = Arc::new(4);
+ /// let _y = x.clone();
+ /// assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4)));
+ /// ```
+ #[inline]
+ #[unstable(feature = "arc_unique", reason = "needs FCP", issue = "27718")]
+ pub fn try_unwrap(this: Self) -> Result<T, Self> {
+ // See `drop` for why all these atomics are like this
+ if this.inner().strong.compare_and_swap(1, 0, Release) != 1 { return Err(this) }
+
+ atomic::fence(Acquire);
+
+ unsafe {
+ let ptr = *this._ptr;
+ let elem = ptr::read(&(*ptr).data);
+
+ // Make a weak pointer to clean up the implicit strong-weak reference
+ let _weak = Weak { _ptr: this._ptr };
+ mem::forget(this);
+
+ Ok(elem)
+ }
+ }
}
impl<T: ?Sized> Arc<T> {
///
/// ```
/// #![feature(arc_weak)]
- ///
/// use std::sync::Arc;
///
/// let five = Arc::new(5);
///
- /// let weak_five = five.downgrade();
+ /// let weak_five = Arc::downgrade(&five);
/// ```
- #[unstable(feature = "arc_weak",
- reason = "Weak pointers may not belong in this module.",
- issue = "27718")]
- pub fn downgrade(&self) -> Weak<T> {
+ #[unstable(feature = "arc_weak", reason = "needs FCP", issue = "27718")]
+ pub fn downgrade(this: &Self) -> Weak<T> {
loop {
// This Relaxed is OK because we're checking the value in the CAS
// below.
- let cur = self.inner().weak.load(Relaxed);
+ let cur = this.inner().weak.load(Relaxed);
// check if the weak counter is currently "locked"; if so, spin.
if cur == usize::MAX { continue }
// Unlike with Clone(), we need this to be an Acquire read to
// synchronize with the write coming from `is_unique`, so that the
// events prior to that write happen before this read.
- if self.inner().weak.compare_and_swap(cur, cur + 1, Acquire) == cur {
- return Weak { _ptr: self._ptr }
+ if this.inner().weak.compare_and_swap(cur, cur + 1, Acquire) == cur {
+ return Weak { _ptr: this._ptr }
}
}
}
/// Get the number of weak references to this value.
#[inline]
- #[unstable(feature = "arc_counts", issue = "27718")]
- pub fn weak_count(this: &Arc<T>) -> usize {
+ #[unstable(feature = "arc_counts", reason = "not clearly useful, and racy", issue = "27718")]
+ #[deprecated(since = "1.4.0", reason = "not clearly useful, and racy")]
+ pub fn weak_count(this: &Self) -> usize {
this.inner().weak.load(SeqCst) - 1
}
/// Get the number of strong references to this value.
#[inline]
- #[unstable(feature = "arc_counts", issue = "27718")]
- pub fn strong_count(this: &Arc<T>) -> usize {
+ #[unstable(feature = "arc_counts", reason = "not clearly useful, and racy", issue = "27718")]
+ #[deprecated(since = "1.4.0", reason = "not clearly useful, and racy")]
+ pub fn strong_count(this: &Self) -> usize {
this.inner().strong.load(SeqCst)
}
}
impl<T: Clone> Arc<T> {
- /// Make a mutable reference from the given `Arc<T>`.
+ #[unstable(feature = "arc_unique", reason = "renamed to Arc::make_mut", issue = "27718")]
+ #[deprecated(since = "1.4.0", reason = "renamed to Arc::make_mut")]
+ pub fn make_unique(this: &mut Self) -> &mut T {
+ Arc::make_mut(this)
+ }
+
+ /// Make a mutable reference into the given `Arc<T>` by cloning the inner
+ /// data if the `Arc<T>` doesn't have one strong reference and no weak
+ /// references.
///
- /// This is also referred to as a copy-on-write operation because the inner
- /// data is cloned if the (strong) reference count is greater than one. If
- /// we hold the only strong reference, any existing weak references will no
- /// longer be upgradeable.
+ /// This is also referred to as a copy-on-write.
///
/// # Examples
///
/// ```
/// #![feature(arc_unique)]
- ///
/// use std::sync::Arc;
///
- /// let mut five = Arc::new(5);
+ /// let mut data = Arc::new(5);
+ ///
+ /// *Arc::make_mut(&mut data) += 1; // Won't clone anything
+ /// let mut other_data = data.clone(); // Won't clone inner data
+ /// *Arc::make_mut(&mut data) += 1; // Clones inner data
+ /// *Arc::make_mut(&mut data) += 1; // Won't clone anything
+ /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
+ ///
+ /// // Note: data and other_data now point to different numbers
+ /// assert_eq!(*data, 8);
+ /// assert_eq!(*other_data, 12);
///
- /// let mut_five = Arc::make_unique(&mut five);
/// ```
#[inline]
- #[unstable(feature = "arc_unique", issue = "27718")]
- pub fn make_unique(this: &mut Arc<T>) -> &mut T {
+ #[unstable(feature = "arc_unique", reason = "needs FCP", issue = "27718")]
+ pub fn make_mut(this: &mut Self) -> &mut T {
// Note that we hold both a strong reference and a weak reference.
// Thus, releasing our strong reference only will not, by itself, cause
// the memory to be deallocated.
}
impl<T: ?Sized> Arc<T> {
- /// Returns a mutable reference to the contained value if the `Arc<T>` is unique.
- ///
- /// Returns `None` if the `Arc<T>` is not unique.
+ /// Returns a mutable reference to the contained value if the `Arc<T>` has
+ /// one strong reference and no weak references.
///
/// # Examples
///
/// ```
- /// #![feature(arc_unique, alloc)]
- ///
- /// extern crate alloc;
- /// # fn main() {
- /// use alloc::arc::Arc;
+ /// #![feature(arc_unique)]
+ /// use std::sync::Arc;
///
/// let mut x = Arc::new(3);
/// *Arc::get_mut(&mut x).unwrap() = 4;
///
/// let _y = x.clone();
/// assert!(Arc::get_mut(&mut x).is_none());
- /// # }
/// ```
#[inline]
- #[unstable(feature = "arc_unique", issue = "27718")]
- pub fn get_mut(this: &mut Arc<T>) -> Option<&mut T> {
+ #[unstable(feature = "arc_unique", reason = "needs FCP", issue = "27718")]
+ pub fn get_mut(this: &mut Self) -> Option<&mut T> {
if this.is_unique() {
// This unsafety is ok because we're guaranteed that the pointer
// returned is the *only* pointer that will ever be returned to T. Our
}
}
-#[unstable(feature = "arc_weak",
- reason = "Weak pointers may not belong in this module.",
- issue = "27718")]
impl<T: ?Sized> Weak<T> {
/// Upgrades a weak reference to a strong reference.
///
///
/// ```
/// #![feature(arc_weak)]
- ///
/// use std::sync::Arc;
///
/// let five = Arc::new(5);
///
- /// let weak_five = five.downgrade();
+ /// let weak_five = Arc::downgrade(&five);
///
/// let strong_five: Option<Arc<_>> = weak_five.upgrade();
/// ```
+ #[unstable(feature = "arc_weak", reason = "needs FCP", issue = "27718")]
pub fn upgrade(&self) -> Option<Arc<T>> {
// We use a CAS loop to increment the strong count instead of a
// fetch_add because once the count hits 0 it must never be above 0.
}
}
-#[unstable(feature = "arc_weak",
- reason = "Weak pointers may not belong in this module.",
- issue = "27718")]
+#[unstable(feature = "arc_weak", reason = "needs FCP", issue = "27718")]
impl<T: ?Sized> Clone for Weak<T> {
/// Makes a clone of the `Weak<T>`.
///
///
/// ```
/// #![feature(arc_weak)]
- ///
/// use std::sync::Arc;
///
- /// let weak_five = Arc::new(5).downgrade();
+ /// let weak_five = Arc::downgrade(&Arc::new(5));
///
/// weak_five.clone();
/// ```
///
/// ```
/// #![feature(arc_weak)]
- ///
/// use std::sync::Arc;
///
/// {
/// let five = Arc::new(5);
- /// let weak_five = five.downgrade();
+ /// let weak_five = Arc::downgrade(&five);
///
/// // stuff
///
/// }
/// {
/// let five = Arc::new(5);
- /// let weak_five = five.downgrade();
+ /// let weak_five = Arc::downgrade(&five);
///
/// // stuff
///
assert!(Arc::get_mut(&mut x).is_none());
drop(y);
assert!(Arc::get_mut(&mut x).is_some());
- let _w = x.downgrade();
+ let _w = Arc::downgrade(&x);
assert!(Arc::get_mut(&mut x).is_none());
}
#[test]
- fn test_cowarc_clone_make_unique() {
+ fn try_unwrap() {
+ let x = Arc::new(3);
+ assert_eq!(Arc::try_unwrap(x), Ok(3));
+ let x = Arc::new(4);
+ let _y = x.clone();
+ assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4)));
+ let x = Arc::new(5);
+ let _w = Arc::downgrade(&x);
+ assert_eq!(Arc::try_unwrap(x), Ok(5));
+ }
+
+ #[test]
+ fn test_cowarc_clone_make_mut() {
let mut cow0 = Arc::new(75);
let mut cow1 = cow0.clone();
let mut cow2 = cow1.clone();
- assert!(75 == *Arc::make_unique(&mut cow0));
- assert!(75 == *Arc::make_unique(&mut cow1));
- assert!(75 == *Arc::make_unique(&mut cow2));
+ assert!(75 == *Arc::make_mut(&mut cow0));
+ assert!(75 == *Arc::make_mut(&mut cow1));
+ assert!(75 == *Arc::make_mut(&mut cow2));
- *Arc::make_unique(&mut cow0) += 1;
- *Arc::make_unique(&mut cow1) += 2;
- *Arc::make_unique(&mut cow2) += 3;
+ *Arc::make_mut(&mut cow0) += 1;
+ *Arc::make_mut(&mut cow1) += 2;
+ *Arc::make_mut(&mut cow2) += 3;
assert!(76 == *cow0);
assert!(77 == *cow1);
assert!(75 == *cow1);
assert!(75 == *cow2);
- *Arc::make_unique(&mut cow0) += 1;
-
+ *Arc::make_mut(&mut cow0) += 1;
assert!(76 == *cow0);
assert!(75 == *cow1);
assert!(75 == *cow2);
#[test]
fn test_cowarc_clone_weak() {
let mut cow0 = Arc::new(75);
- let cow1_weak = cow0.downgrade();
+ let cow1_weak = Arc::downgrade(&cow0);
assert!(75 == *cow0);
assert!(75 == *cow1_weak.upgrade().unwrap());
- *Arc::make_unique(&mut cow0) += 1;
+ *Arc::make_mut(&mut cow0) += 1;
assert!(76 == *cow0);
assert!(cow1_weak.upgrade().is_none());
#[test]
fn test_live() {
let x = Arc::new(5);
- let y = x.downgrade();
+ let y = Arc::downgrade(&x);
assert!(y.upgrade().is_some());
}
#[test]
fn test_dead() {
let x = Arc::new(5);
- let y = x.downgrade();
+ let y = Arc::downgrade(&x);
drop(x);
assert!(y.upgrade().is_none());
}
}
let a = Arc::new(Cycle { x: Mutex::new(None) });
- let b = a.clone().downgrade();
+ let b = Arc::downgrade(&a.clone());
*a.x.lock().unwrap() = Some(b);
// hopefully we don't double-free (or leak)...
fn drop_arc_weak() {
let mut canary = atomic::AtomicUsize::new(0);
let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize));
- let arc_weak = arc.downgrade();
+ let arc_weak = Arc::downgrade(&arc);
assert!(canary.load(Acquire) == 0);
drop(arc);
assert!(canary.load(Acquire) == 1);
fn test_strong_count() {
let a = Arc::new(0u32);
assert!(Arc::strong_count(&a) == 1);
- let w = a.downgrade();
+ let w = Arc::downgrade(&a);
assert!(Arc::strong_count(&a) == 1);
let b = w.upgrade().expect("");
assert!(Arc::strong_count(&b) == 2);
let a = Arc::new(0u32);
assert!(Arc::strong_count(&a) == 1);
assert!(Arc::weak_count(&a) == 0);
- let w = a.downgrade();
+ let w = Arc::downgrade(&a);
assert!(Arc::strong_count(&a) == 1);
assert!(Arc::weak_count(&a) == 1);
let x = w.clone();
let c = a.clone();
assert!(Arc::strong_count(&a) == 2);
assert!(Arc::weak_count(&a) == 0);
- let d = c.downgrade();
+ let d = Arc::downgrade(&c);
assert!(Arc::weak_count(&c) == 1);
assert!(Arc::strong_count(&c) == 2);
fn test_unsized() {
let x: Arc<[i32]> = Arc::new([1, 2, 3]);
assert_eq!(format!("{:?}", x), "[1, 2, 3]");
- let y = x.clone().downgrade();
+ let y = Arc::downgrade(&x.clone());
drop(x);
assert!(y.upgrade().is_none());
}