@@ -165,7 +165,7 @@ impl<T: Share + Send> Drop for Arc<T> {
165165 // Because `fetch_sub` is already atomic, we do not need to synchronize
166166 // with other threads unless we are going to delete the object. This
167167 // same logic applies to the below `fetch_sub` to the `weak` count.
168- if self . inner ( ) . strong . fetch_sub ( 1 , atomics:: Release ) != 0 { return }
168+ if self . inner ( ) . strong . fetch_sub ( 1 , atomics:: Release ) != 1 { return }
169169
170170 // This fence is needed to prevent reordering of use of the data and
171171 // deletion of the data. Because it is marked `Release`, the
@@ -190,7 +190,7 @@ impl<T: Share + Send> Drop for Arc<T> {
190190 // allocation itself (there may still be weak pointers lying around).
191191 unsafe { drop ( ptr:: read ( & self . inner ( ) . data ) ) ; }
192192
193- if self . inner ( ) . weak . fetch_sub ( 1 , atomics:: Release ) == 0 {
193+ if self . inner ( ) . weak . fetch_sub ( 1 , atomics:: Release ) == 1 {
194194 atomics:: fence ( atomics:: Acquire ) ;
195195 unsafe { global_heap:: exchange_free ( self . x as * u8 ) }
196196 }
@@ -240,7 +240,7 @@ impl<T: Share + Send> Drop for Weak<T> {
240240 // If we find out that we were the last weak pointer, then its time to
241241 // deallocate the data entirely. See the discussion in Arc::drop() about
242242 // the memory orderings
243- if self . inner ( ) . weak . fetch_sub ( 1 , atomics:: Release ) == 0 {
243+ if self . inner ( ) . weak . fetch_sub ( 1 , atomics:: Release ) == 1 {
244244 atomics:: fence ( atomics:: Acquire ) ;
245245 unsafe { global_heap:: exchange_free ( self . x as * u8 ) }
246246 }
@@ -251,9 +251,24 @@ impl<T: Share + Send> Drop for Weak<T> {
251251#[ allow( experimental) ]
252252mod tests {
253253 use super :: { Arc , Weak } ;
254+ use std:: sync:: atomics;
255+ use std:: task;
254256 use Mutex ;
255257
256- use std:: task;
258+ struct Canary ( * mut atomics:: AtomicUint ) ;
259+
260+ impl Drop for Canary
261+ {
262+ fn drop ( & mut self ) {
263+ unsafe {
264+ match * self {
265+ Canary ( c) => {
266+ ( * c) . fetch_add ( 1 , atomics:: SeqCst ) ;
267+ }
268+ }
269+ }
270+ }
271+ }
257272
258273 #[ test]
259274 fn manually_share_arc ( ) {
@@ -349,4 +364,23 @@ mod tests {
349364
350365 // hopefully we don't double-free (or leak)...
351366 }
367+
368+ #[ test]
369+ fn drop_arc ( ) {
370+ let mut canary = atomics:: AtomicUint :: new ( 0 ) ;
371+ let x = Arc :: new ( Canary ( & mut canary as * mut atomics:: AtomicUint ) ) ;
372+ drop ( x) ;
373+ assert ! ( canary. load( atomics:: Acquire ) == 1 ) ;
374+ }
375+
376+ #[ test]
377+ fn drop_arc_weak ( ) {
378+ let mut canary = atomics:: AtomicUint :: new ( 0 ) ;
379+ let arc = Arc :: new ( Canary ( & mut canary as * mut atomics:: AtomicUint ) ) ;
380+ let arc_weak = arc. downgrade ( ) ;
381+ assert ! ( canary. load( atomics:: Acquire ) == 0 ) ;
382+ drop ( arc) ;
383+ assert ! ( canary. load( atomics:: Acquire ) == 1 ) ;
384+ drop ( arc_weak) ;
385+ }
352386}
0 commit comments