@@ -191,6 +191,45 @@ impl<T> Arc<T> {
191
191
} ;
192
192
Arc { _ptr : unsafe { NonZero :: new ( Box :: into_raw ( x) ) } }
193
193
}
194
+
195
+ /// Unwraps the contained value if the `Arc<T>` has only one strong reference.
196
+ /// This will succeed even if there are outstanding weak references.
197
+ ///
198
+ /// Otherwise, an `Err` is returned with the same `Arc<T>`.
199
+ ///
200
+ /// # Examples
201
+ ///
202
+ /// ```
203
+ /// use std::sync::Arc;
204
+ ///
205
+ /// let x = Arc::new(3);
206
+ /// assert_eq!(Arc::try_unwrap(x), Ok(3));
207
+ ///
208
+ /// let x = Arc::new(4);
209
+ /// let _y = x.clone();
210
+ /// assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4)));
211
+ /// ```
212
+ #[ inline]
213
+ #[ unstable( feature = "arc_unwrap" , reason = "was missing, so is technically new" ) ]
214
+ pub fn try_unwrap ( this : Arc < T > ) -> Result < T , Arc < T > > {
215
+ // See `drop` for impl details
216
+ if self . inner ( ) . strong . compare_and_swap ( 1 , 0 , Release ) != 1 { return Err ( self ) }
217
+
218
+ // ~~ magic ~~
219
+ atomic:: fence ( Acquire ) ;
220
+
221
+ unsafe {
222
+ let ptr = * self . _ptr ;
223
+
224
+ let elem = ptr:: read ( & ( * ptr) . data ) ;
225
+
226
+ if self . inner ( ) . weak . fetch_sub ( 1 , Release ) == 1 {
227
+ atomic:: fence ( Acquire ) ;
228
+ deallocate ( ptr as * mut u8 , size_of_val ( & * ptr) , align_of_val ( & * ptr) )
229
+ }
230
+ Ok ( elem)
231
+ }
232
+ }
194
233
}
195
234
196
235
impl < T : ?Sized > Arc < T > {
@@ -885,6 +924,18 @@ mod tests {
885
924
assert ! ( Arc :: get_mut( & mut x) . is_none( ) ) ;
886
925
}
887
926
927
+ #[ test]
928
+ fn try_unwrap ( ) {
929
+ let x = Arc :: new ( 3 ) ;
930
+ assert_eq ! ( Arc :: try_unwrap( x) , Ok ( 3 ) ) ;
931
+ let x = Arc :: new ( 4 ) ;
932
+ let _y = x. clone ( ) ;
933
+ assert_eq ! ( Arc :: try_unwrap( x) , Err ( Arc :: new( 4 ) ) ) ;
934
+ let x = Arc :: new ( 5 ) ;
935
+ let _w = x. downgrade ( ) ;
936
+ assert_eq ! ( Arc :: try_unwrap( x) , Ok ( 5 ) ) ;
937
+ }
938
+
888
939
#[ test]
889
940
fn test_cowarc_clone_make_mut ( ) {
890
941
let mut cow0 = Arc :: new ( 75 ) ;
0 commit comments