@@ -11,7 +11,7 @@ use core::sync::atomic;
1111use core:: sync:: atomic:: Ordering :: { Acquire , Relaxed , Release , SeqCst } ;
1212use core:: borrow;
1313use core:: fmt;
14- use core:: cmp:: Ordering ;
14+ use core:: cmp:: { self , Ordering } ;
1515use core:: intrinsics:: abort;
1616use core:: mem:: { self , align_of_val, size_of_val} ;
1717use core:: ops:: { Deref , Receiver } ;
@@ -1131,10 +1131,48 @@ impl<T: ?Sized> Weak<T> {
11311131 }
11321132 }
11331133
1134- // Due to the implicit weak pointer added when any strong pointers are
1135- // around, we cannot implement `weak_count` correctly since it necessarily
1136- // requires accessing the strong count and weak count in an unsynchronized
1137- // fashion.
1134+ /// Gets an approximation of the number of `Weak` pointers pointing to this
1135+ /// value.
1136+ ///
1137+ /// If `self` was created using [`Weak::new`], this will return 0. If not,
1138+ /// the returned value is at least 1, since `self` still points to the
1139+ /// value.
1140+ ///
1141+ /// # Accuracy
1142+ ///
1143+ /// Due to implementation details, the returned value can be off by 1 in
1144+ /// either direction when other threads are manipulating any `Arc`s or
1145+ /// `Weak`s pointing to the same value.
1146+ ///
1147+ /// [`Weak::new`]: #method.new
1148+ #[ unstable( feature = "weak_counts" , issue = "0" ) ]
1149+ pub fn weak_count ( & self ) -> usize {
1150+ // Due to the implicit weak pointer added when any strong pointers are
1151+ // around, we cannot implement `weak_count` correctly since it
1152+ // necessarily requires accessing the strong count and weak count in an
1153+ // unsynchronized fashion. So this version is a bit racy.
1154+ if let Some ( inner) = self . inner ( ) {
1155+ let strong = inner. strong . load ( SeqCst ) ;
1156+ let weak = inner. weak . load ( SeqCst ) ;
1157+ if strong == 0 {
1158+ // If the last `Arc` has *just* been dropped, it might not yet
1159+ // have removed the implicit weak count, so the value we get
1160+ // here might be 1 too high.
1161+ weak
1162+ } else {
1163+ // As long as there's still at least 1 `Arc` around, subtract
1164+ // the implicit weak pointer.
1165+ // Note that the last `Arc` might get dropped between the 2
1166+ // loads we do above, removing the implicit weak pointer. This
1167+ // means that the value might be 1 too low here. In order to not
1168+ // return 0 here (which would happen if we're the only weak
1169+ // pointer), we guard against that specifically.
1170+ cmp:: max ( 1 , weak - 1 )
1171+ }
1172+ } else {
1173+ 0
1174+ }
1175+ }
11381176
11391177 /// Return `None` when the pointer is dangling and there is no allocated `ArcInner`,
11401178 /// i.e., this `Weak` was created by `Weak::new`
@@ -1655,6 +1693,33 @@ mod tests {
16551693 assert ! ( Arc :: get_mut( & mut x) . is_none( ) ) ;
16561694 }
16571695
1696+ #[ test]
1697+ fn weak_counts ( ) {
1698+ assert_eq ! ( Weak :: weak_count( & Weak :: <u64 >:: new( ) ) , 0 ) ;
1699+ assert_eq ! ( Weak :: strong_count( & Weak :: <u64 >:: new( ) ) , 0 ) ;
1700+
1701+ let a = Arc :: new ( 0 ) ;
1702+ let w = Arc :: downgrade ( & a) ;
1703+ assert_eq ! ( Weak :: strong_count( & w) , 1 ) ;
1704+ assert_eq ! ( Weak :: weak_count( & w) , 1 ) ;
1705+ let w2 = w. clone ( ) ;
1706+ assert_eq ! ( Weak :: strong_count( & w) , 1 ) ;
1707+ assert_eq ! ( Weak :: weak_count( & w) , 2 ) ;
1708+ assert_eq ! ( Weak :: strong_count( & w2) , 1 ) ;
1709+ assert_eq ! ( Weak :: weak_count( & w2) , 2 ) ;
1710+ drop ( w) ;
1711+ assert_eq ! ( Weak :: strong_count( & w2) , 1 ) ;
1712+ assert_eq ! ( Weak :: weak_count( & w2) , 1 ) ;
1713+ let a2 = a. clone ( ) ;
1714+ assert_eq ! ( Weak :: strong_count( & w2) , 2 ) ;
1715+ assert_eq ! ( Weak :: weak_count( & w2) , 1 ) ;
1716+ drop ( a2) ;
1717+ drop ( a) ;
1718+ assert_eq ! ( Weak :: strong_count( & w2) , 0 ) ;
1719+ assert_eq ! ( Weak :: weak_count( & w2) , 1 ) ;
1720+ drop ( w2) ;
1721+ }
1722+
16581723 #[ test]
16591724 fn try_unwrap ( ) {
16601725 let x = Arc :: new ( 3 ) ;
0 commit comments