diff --git a/conc/src/atomic.rs b/conc/src/atomic.rs index b87b636..b4c49b8 100644 --- a/conc/src/atomic.rs +++ b/conc/src/atomic.rs @@ -331,7 +331,7 @@ mod tests { use std::sync::atomic::AtomicUsize; use std::{thread, ptr}; - #[derive(Clone)] + #[derive(Clone, Debug)] struct Dropper { d: Arc, } @@ -421,12 +421,7 @@ mod tests { assert!(opt.load(atomic::Ordering::Relaxed).is_none()); - // To check that GC doesn't segfault or something. - let _ = ::try_gc(); - let _ = ::try_gc(); - let _ = ::try_gc(); - let _ = ::try_gc(); - let _ = ::try_gc(); + while ::try_gc().is_err() {} } #[test] @@ -455,12 +450,7 @@ mod tests { assert!(opt.load(atomic::Ordering::Relaxed).is_none()); - // To check that GC doesn't segfault or something. - let _ = ::try_gc(); - let _ = ::try_gc(); - let _ = ::try_gc(); - let _ = ::try_gc(); - let _ = ::try_gc(); + while ::try_gc().is_err() {} } } @@ -554,6 +544,59 @@ mod tests { #[test] fn drop3() { + let drops = Arc::new(AtomicUsize::default()); + + let d = Dropper { + d: drops.clone(), + }; + + for _ in 0..16 { + let atomic = Atomic::new(Some(Box::new(d.clone()))); + atomic.store(Some(Box::new(d.clone())), atomic::Ordering::Relaxed); + let b = Box::new(d.clone()); + let bptr = &*b as *const Dropper; + atomic.swap(Some(b), atomic::Ordering::Relaxed); + atomic.compare_and_swap( + Some(bptr), + Some(Box::new(d.clone())), + atomic::Ordering::Relaxed + ).unwrap(); + for _ in 0..10 { + atomic.compare_and_swap( + Some(bptr), + None, + atomic::Ordering::Relaxed + ).unwrap_err(); + unsafe { + atomic.compare_and_swap_raw( + bptr, + ptr::null_mut(), + atomic::Ordering::Relaxed + ).unwrap_err(); + } + } + let b = Box::new(d.clone()); + let bptr = &*b as *const Dropper; + atomic.swap(Some(b), atomic::Ordering::Relaxed); + unsafe { + atomic.compare_and_swap_raw( + bptr, + Box::into_raw(Box::new(d.clone())), + atomic::Ordering::Relaxed + ).unwrap(); + } + + atomic.store(None, atomic::Ordering::Relaxed); + } + + drop(d); + while ::try_gc().is_err() {} + + assert_eq!(drops.load(atomic::Ordering::Relaxed), 16 * 6); + } + + #[test] + fn drop4() { for i in 0..256 { let opt = Arc::new(Atomic::new(Some(Box::new(i)))); let g = opt.load(atomic::Ordering::Relaxed); diff --git a/conc/src/guard.rs b/conc/src/guard.rs index 32ab119..39c8221 100644 --- a/conc/src/guard.rs +++ b/conc/src/guard.rs @@ -29,9 +29,11 @@ pub fn debug_assert_no_create() { /// This "guards" the held pointer against garbage collection. First when all guards of said /// pointer is gone (the data is unreachable), it can be collected. // TODO: Remove this `'static` bound. -#[must_use = "You are getting a `conc::Guard` without using it, which means it is potentially \ - unnecessary overhead. Consider replacing the method with something that doesn't \ - return a guard."] +#[must_use = "\ + You are getting a `conc::Guard` without using it, which means it is potentially \ + unnecessary overhead. Consider replacing the method with something that doesn't \ + return a guard.\ +"] #[derive(Debug)] pub struct Guard { /// The inner hazard.