@@ -2446,7 +2446,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
24462446 #[ inline]
24472447 #[ stable( feature = "arc_unique" , since = "1.4.0" ) ]
24482448 pub fn get_mut ( this : & mut Self ) -> Option < & mut T > {
2449- if this . is_unique ( ) {
2449+ if Self :: is_unique ( this ) {
24502450 // This unsafety is ok because we're guaranteed that the pointer
24512451 // returned is the *only* pointer that will ever be returned to T. Our
24522452 // reference count is guaranteed to be 1 at this point, and we required
@@ -2526,28 +2526,86 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
25262526 unsafe { & mut ( * this. ptr . as_ptr ( ) ) . data }
25272527 }
25282528
2529- /// Determine whether this is the unique reference (including weak refs) to
2530- /// the underlying data.
2529+ /// Determine whether this is the unique reference to the underlying data.
2530+ /// Returns `true` if there are no other `Arc` or [`Weak`] pointers to the same allocation;
2531+ /// returns `false` otherwise.
25312532 ///
2532- /// Note that this requires locking the weak ref count.
2533- fn is_unique ( & mut self ) -> bool {
2533+ /// If this function returns `true`,
2534+ /// then is guaranteed to be safe to call [`get_mut_unchecked`] on this `Arc`,
2535+ /// so long as no clones occur in between.
2536+ ///
2537+ /// # Examples
2538+ ///
2539+ /// ```
2540+ /// #![feature(arc_is_unique)]
2541+ ///
2542+ /// use std::sync::Arc;
2543+ ///
2544+ /// let x = Arc::new(3);
2545+ /// assert!(Arc::is_unique(&x));
2546+ ///
2547+ /// let y = Arc::clone(&x);
2548+ /// assert!(!Arc::is_unique(&x));
2549+ /// drop(y);
2550+ ///
2551+ /// // Weak references also count, because they could be upgraded at any time.
2552+ /// let z = Arc::downgrade(&x);
2553+ /// assert!(!Arc::is_unique(&x));
2554+ /// ```
2555+ ///
2556+ /// # Pointer invalidation
2557+ ///
2558+ /// This function
2559+ /// will always return the same value as `Arc::get_mut(arc).is_some()`.
2560+ /// However, unlike that operation
2561+ /// it does not produce any mutable references to the underlying data,
2562+ /// meaning no pointers to the data inside the `Arc` are invalidated by the call.
2563+ /// Thus, the following code is valid,
2564+ /// even though it would be UB if it used `Arc::get_mut`:
2565+ ///
2566+ /// ```
2567+ /// #![feature(arc_is_unique)]
2568+ ///
2569+ /// use std::sync::Arc;
2570+ ///
2571+ /// let arc = Arc::new(5);
2572+ /// let pointer: *const i32 = &*arc;
2573+ /// assert!(Arc::is_unique(&arc));
2574+ /// assert_eq!(unsafe { *pointer }, 5);
2575+ /// ```
2576+ ///
2577+ /// # Atomic orderings
2578+ ///
2579+ /// Concurrent drops to other `Arc` pointers to the same allocation
2580+ /// will synchronize with this call -
2581+ /// that is, this call performs an `Acquire` operation
2582+ /// on the underlying strong and weak ref counts.
2583+ /// This ensures that calling `get_mut_unchecked` is safe.
2584+ ///
2585+ /// Note that this operation requires locking the weak ref count,
2586+ /// so concurrent calls to `downgrade` may spin-loop for a short period of time.
2587+ ///
2588+ /// [`get_mut_unchecked`]: Self::get_mut_unchecked
2589+ #[ inline]
2590+ #[ unstable( feature = "arc_is_unique" , issue = "138938" ) ]
2591+ pub fn is_unique ( this : & Self ) -> bool {
25342592 // lock the weak pointer count if we appear to be the sole weak pointer
25352593 // holder.
25362594 //
25372595 // The acquire label here ensures a happens-before relationship with any
25382596 // writes to `strong` (in particular in `Weak::upgrade`) prior to decrements
25392597 // of the `weak` count (via `Weak::drop`, which uses release). If the upgraded
25402598 // weak ref was never dropped, the CAS here will fail so we do not care to synchronize.
2541- if self . inner ( ) . weak . compare_exchange ( 1 , usize:: MAX , Acquire , Relaxed ) . is_ok ( ) {
2599+ if this . inner ( ) . weak . compare_exchange ( 1 , usize:: MAX , Acquire , Relaxed ) . is_ok ( ) {
25422600 // This needs to be an `Acquire` to synchronize with the decrement of the `strong`
25432601 // counter in `drop` -- the only access that happens when any but the last reference
25442602 // is being dropped.
2545- let unique = self . inner ( ) . strong . load ( Acquire ) == 1 ;
2603+ let unique = this . inner ( ) . strong . load ( Acquire ) == 1 ;
25462604
25472605 // The release write here synchronizes with a read in `downgrade`,
25482606 // effectively preventing the above read of `strong` from happening
25492607 // after the write.
2550- self . inner ( ) . weak . store ( 1 , Release ) ; // release the lock
2608+ this . inner ( ) . weak . store ( 1 , Release ) ; // release the lock
25512609 unique
25522610 } else {
25532611 false
0 commit comments