use haphazard::*;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::sync::Arc;
struct CountDrops(Arc<AtomicUsize>);
impl Drop for CountDrops {
fn drop(&mut self) {
self.0.fetch_add(1, Ordering::SeqCst);
}
}
#[test]
fn acquires_multiple() {
let drops_42 = Arc::new(AtomicUsize::new(0));
let domain = Domain::new(&());
let x = AtomicPtr::from(Box::new((42, CountDrops(Arc::clone(&drops_42)))));
let y = AtomicPtr::from(Box::new((42, CountDrops(Arc::clone(&drops_42)))));
let mut hazptr_array = HazardPointer::many_in_domain(&domain);
let [mut one, mut two] = hazptr_array.as_refs();
let my_x = unsafe { x.load(&mut one).expect("not null") };
let my_y = unsafe { y.load(&mut two).expect("not null") };
assert_eq!(my_x.0, 42);
assert_eq!(my_y.0, 42);
drop(hazptr_array);
domain.eager_reclaim();
assert_eq!(drops_42.load(Ordering::SeqCst), 0);
unsafe { x.retire_in(&domain) };
domain.eager_reclaim();
assert_eq!(drops_42.load(Ordering::SeqCst), 1);
unsafe { y.retire_in(&domain) };
domain.eager_reclaim();
assert_eq!(drops_42.load(Ordering::SeqCst), 2);
}
#[test]
fn feels_good() {
let drops_42 = Arc::new(AtomicUsize::new(0));
let x = AtomicPtr::from(Box::new((42, CountDrops(Arc::clone(&drops_42)))));
let mut h = HazardPointer::new();
let my_x = x.safe_load(&mut h).expect("not null");
assert_eq!(my_x.0, 42);
h.reset_protection();
let my_x = x.safe_load(&mut h).expect("not null");
assert_eq!(my_x.0, 42);
drop(h);
let mut h = HazardPointer::new();
let my_x = x.safe_load(&mut h).expect("not null");
let mut h_tmp = HazardPointer::new();
let _ = x.safe_load(&mut h_tmp).expect("not null");
drop(h_tmp);
let drops_9001 = Arc::new(AtomicUsize::new(0));
let old = x
.swap(Box::new((9001, CountDrops(Arc::clone(&drops_9001)))))
.expect("not null");
let mut h2 = HazardPointer::new();
let my_x2 = x.safe_load(&mut h2).expect("not null");
assert_eq!(my_x.0, 42);
assert_eq!(my_x2.0, 9001);
unsafe { old.retire() };
assert_eq!(drops_42.load(Ordering::SeqCst), 0);
assert_eq!(my_x.0, 42);
let n = Domain::global().eager_reclaim();
assert_eq!(n, 0);
assert_eq!(drops_42.load(Ordering::SeqCst), 0);
assert_eq!(my_x.0, 42);
drop(h);
assert_eq!(drops_42.load(Ordering::SeqCst), 0);
let n = Domain::global().eager_reclaim();
assert_eq!(n, 1);
assert_eq!(drops_42.load(Ordering::SeqCst), 1);
assert_eq!(drops_9001.load(Ordering::SeqCst), 0);
drop(h2);
let n = Domain::global().eager_reclaim();
assert_eq!(n, 0);
assert_eq!(drops_9001.load(Ordering::SeqCst), 0);
unsafe { x.retire() };
let n = Domain::global().eager_reclaim();
assert_eq!(n, 1);
assert_eq!(drops_9001.load(Ordering::SeqCst), 1);
}
#[test]
fn drop_domain() {
let domain = Domain::new(&());
let drops_42 = Arc::new(AtomicUsize::new(0));
let x = AtomicPtr::from(Box::new((42, CountDrops(Arc::clone(&drops_42)))));
let mut h = HazardPointer::new_in_domain(&domain);
let my_x = unsafe { x.load(&mut h).expect("not null") };
assert_eq!(my_x.0, 42);
let drops_9001 = Arc::new(AtomicUsize::new(0));
let old = x
.swap(Box::new((9001, CountDrops(Arc::clone(&drops_9001)))))
.expect("not null");
assert_eq!(drops_42.load(Ordering::SeqCst), 0);
assert_eq!(my_x.0, 42);
unsafe { old.retire_in(&domain) };
assert_eq!(drops_42.load(Ordering::SeqCst), 0);
assert_eq!(my_x.0, 42);
let n = domain.eager_reclaim();
assert_eq!(n, 0);
assert_eq!(drops_42.load(Ordering::SeqCst), 0);
assert_eq!(my_x.0, 42);
h.reset_protection();
let n = domain.eager_reclaim();
assert_eq!(n, 1);
assert_eq!(drops_42.load(Ordering::SeqCst), 1);
drop(h);
unsafe { x.retire_in(&domain) };
drop(domain);
assert_eq!(drops_9001.load(Ordering::SeqCst), 1);
}