@@ -165,7 +165,7 @@ impl<T: Share + Send> Drop for Arc<T> {
165
165
// Because `fetch_sub` is already atomic, we do not need to synchronize
166
166
// with other threads unless we are going to delete the object. This
167
167
// 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 }
169
169
170
170
// This fence is needed to prevent reordering of use of the data and
171
171
// deletion of the data. Because it is marked `Release`, the
@@ -190,7 +190,7 @@ impl<T: Share + Send> Drop for Arc<T> {
190
190
// allocation itself (there may still be weak pointers lying around).
191
191
unsafe { drop ( ptr:: read ( & self . inner ( ) . data ) ) ; }
192
192
193
- if self . inner ( ) . weak . fetch_sub ( 1 , atomics:: Release ) == 0 {
193
+ if self . inner ( ) . weak . fetch_sub ( 1 , atomics:: Release ) == 1 {
194
194
atomics:: fence ( atomics:: Acquire ) ;
195
195
unsafe { global_heap:: exchange_free ( self . x as * u8 ) }
196
196
}
@@ -240,7 +240,7 @@ impl<T: Share + Send> Drop for Weak<T> {
240
240
// If we find out that we were the last weak pointer, then its time to
241
241
// deallocate the data entirely. See the discussion in Arc::drop() about
242
242
// 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 {
244
244
atomics:: fence ( atomics:: Acquire ) ;
245
245
unsafe { global_heap:: exchange_free ( self . x as * u8 ) }
246
246
}
@@ -251,9 +251,24 @@ impl<T: Share + Send> Drop for Weak<T> {
251
251
#[ allow( experimental) ]
252
252
mod tests {
253
253
use super :: { Arc , Weak } ;
254
+ use std:: sync:: atomics;
255
+ use std:: task;
254
256
use Mutex ;
255
257
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
+ }
257
272
258
273
#[ test]
259
274
fn manually_share_arc ( ) {
@@ -349,4 +364,23 @@ mod tests {
349
364
350
365
// hopefully we don't double-free (or leak)...
351
366
}
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
+ }
352
386
}
0 commit comments