@@ -12,7 +12,7 @@ use core::sync::atomic;
1212use core:: sync:: atomic:: Ordering :: { Acquire , Relaxed , Release , SeqCst } ;
1313use core:: borrow;
1414use core:: fmt;
15- use core:: cmp:: { self , Ordering } ;
15+ use core:: cmp:: Ordering ;
1616use core:: iter;
1717use core:: intrinsics:: abort;
1818use core:: mem:: { self , align_of, align_of_val, size_of_val} ;
@@ -1529,7 +1529,7 @@ impl<T: ?Sized> Weak<T> {
15291529 /// If `self` was created using [`Weak::new`], this will return 0.
15301530 ///
15311531 /// [`Weak::new`]: #method.new
1532- #[ unstable ( feature = "weak_counts" , issue = "57977 " ) ]
1532+ #[ stable ( feature = "weak_counts" , since = "1.41.0 " ) ]
15331533 pub fn strong_count ( & self ) -> usize {
15341534 if let Some ( inner) = self . inner ( ) {
15351535 inner. strong . load ( SeqCst )
@@ -1541,9 +1541,8 @@ impl<T: ?Sized> Weak<T> {
15411541 /// Gets an approximation of the number of `Weak` pointers pointing to this
15421542 /// allocation.
15431543 ///
1544- /// If `self` was created using [`Weak::new`], this will return 0. If not,
1545- /// the returned value is at least 1, since `self` still points to the
1546- /// allocation.
1544+ /// If `self` was created using [`Weak::new`], or if there are no remaining
1545+ /// strong pointers, this will return 0.
15471546 ///
15481547 /// # Accuracy
15491548 ///
@@ -1552,31 +1551,22 @@ impl<T: ?Sized> Weak<T> {
15521551 /// `Weak`s pointing to the same allocation.
15531552 ///
15541553 /// [`Weak::new`]: #method.new
1555- #[ unstable( feature = "weak_counts" , issue = "57977" ) ]
1556- pub fn weak_count ( & self ) -> Option < usize > {
1557- // Due to the implicit weak pointer added when any strong pointers are
1558- // around, we cannot implement `weak_count` correctly since it
1559- // necessarily requires accessing the strong count and weak count in an
1560- // unsynchronized fashion. So this version is a bit racy.
1554+ #[ stable( feature = "weak_counts" , since = "1.41.0" ) ]
1555+ pub fn weak_count ( & self ) -> usize {
15611556 self . inner ( ) . map ( |inner| {
1562- let strong = inner. strong . load ( SeqCst ) ;
15631557 let weak = inner. weak . load ( SeqCst ) ;
1558+ let strong = inner. strong . load ( SeqCst ) ;
15641559 if strong == 0 {
1565- // If the last `Arc` has *just* been dropped, it might not yet
1566- // have removed the implicit weak count, so the value we get
1567- // here might be 1 too high.
1568- weak
1560+ 0
15691561 } else {
1570- // As long as there's still at least 1 `Arc` around, subtract
1571- // the implicit weak pointer.
1572- // Note that the last `Arc` might get dropped between the 2
1573- // loads we do above, removing the implicit weak pointer. This
1574- // means that the value might be 1 too low here. In order to not
1575- // return 0 here (which would happen if we're the only weak
1576- // pointer), we guard against that specifically.
1577- cmp:: max ( 1 , weak - 1 )
1562+ // Since we observed that there was at least one strong pointer
1563+ // after reading the weak count, we know that the implicit weak
1564+ // reference (present whenever any strong references are alive)
1565+ // was still around when we observed the weak count, and can
1566+ // therefore safely subtract it.
1567+ weak - 1
15781568 }
1579- } )
1569+ } ) . unwrap_or ( 0 )
15801570 }
15811571
15821572 /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`,
0 commit comments