@@ -12,7 +12,7 @@ use core::sync::atomic;
12
12
use core:: sync:: atomic:: Ordering :: { Acquire , Relaxed , Release , SeqCst } ;
13
13
use core:: borrow;
14
14
use core:: fmt;
15
- use core:: cmp:: { self , Ordering } ;
15
+ use core:: cmp:: Ordering ;
16
16
use core:: iter;
17
17
use core:: intrinsics:: abort;
18
18
use core:: mem:: { self , align_of, align_of_val, size_of_val} ;
@@ -1529,7 +1529,7 @@ impl<T: ?Sized> Weak<T> {
1529
1529
/// If `self` was created using [`Weak::new`], this will return 0.
1530
1530
///
1531
1531
/// [`Weak::new`]: #method.new
1532
- #[ unstable ( feature = "weak_counts" , issue = "57977 " ) ]
1532
+ #[ stable ( feature = "weak_counts" , since = "1.41.0 " ) ]
1533
1533
pub fn strong_count ( & self ) -> usize {
1534
1534
if let Some ( inner) = self . inner ( ) {
1535
1535
inner. strong . load ( SeqCst )
@@ -1541,9 +1541,8 @@ impl<T: ?Sized> Weak<T> {
1541
1541
/// Gets an approximation of the number of `Weak` pointers pointing to this
1542
1542
/// allocation.
1543
1543
///
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.
1547
1546
///
1548
1547
/// # Accuracy
1549
1548
///
@@ -1552,31 +1551,22 @@ impl<T: ?Sized> Weak<T> {
1552
1551
/// `Weak`s pointing to the same allocation.
1553
1552
///
1554
1553
/// [`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 {
1561
1556
self . inner ( ) . map ( |inner| {
1562
- let strong = inner. strong . load ( SeqCst ) ;
1563
1557
let weak = inner. weak . load ( SeqCst ) ;
1558
+ let strong = inner. strong . load ( SeqCst ) ;
1564
1559
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
1569
1561
} 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
1578
1568
}
1579
- } )
1569
+ } ) . unwrap_or ( 0 )
1580
1570
}
1581
1571
1582
1572
/// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`,
0 commit comments