use super::*;
use loom::sync::atomic::{AtomicBool, AtomicU8, Ordering};
use loom::sync::Arc;
use loom::thread;
const KEY1: &str = "7mohtcOFVz";
const KEY2: &str = "c1E51sSEyx";
#[test]
fn test_non_blocking() {
loom::model(|| {
let counter = Arc::new(AtomicU8::new(0));
let ack1 = Arc::new(AtomicBool::new(false));
let ack2 = Arc::new(AtomicBool::new(false));
let hasher = fnv::FnvBuildHasher::default();
assert_ne!(hasher.hash_one("a"), hasher.hash_one("b"));
let fett = Arc::new(Fett::with_hasher(hasher, {
let counter = counter.clone();
let ack1 = ack1.clone();
let ack2 = ack2.clone();
move |key| {
let count = counter.fetch_add(1, Ordering::Relaxed);
if count == 0 {
ack1.store(true, Ordering::Release);
while !ack2.load(Ordering::Acquire) {
thread::yield_now();
}
} else if count == 1 {
ack2.store(true, Ordering::Release);
while !ack1.load(Ordering::Acquire) {
thread::yield_now();
}
}
match *key {
"a" => 0,
"b" => 1,
_ => unreachable!(),
}
}
}));
let b = thread::spawn({
let fett = fett.clone();
move || {
assert_eq!(fett.get("b"), 1);
}
});
assert_eq!(fett.get("a"), 0);
b.join().unwrap();
assert_eq!(counter.load(Ordering::Relaxed), 2);
});
}
#[test]
fn test_blocking_same() {
loom::model(|| {
let counter = Arc::new(AtomicU8::new(0));
let fett = Arc::new(Fett::new({
let counter = counter.clone();
move |_key| {
counter.fetch_add(1, Ordering::Relaxed);
0
}
}));
let a = thread::spawn({
let fett = fett.clone();
move || {
fett.get("a");
}
});
fett.get("a");
a.join().unwrap();
assert_eq!(counter.load(Ordering::Relaxed), 1);
});
}
#[test]
fn test_blocking_collision() {
loom::model(|| {
let counter = Arc::new(AtomicU8::new(0));
let observed_concurrency = Arc::new(AtomicBool::new(false));
let hasher = fnv::FnvBuildHasher::default();
assert_eq!(hasher.hash_one(KEY1), hasher.hash_one(KEY2));
let fett = Arc::new(Fett::with_hasher(hasher, {
let counter = counter.clone();
let observed_concurrency = observed_concurrency.clone();
move |key| {
let old = counter.load(Ordering::Acquire);
thread::yield_now();
if counter.fetch_add(1, Ordering::Release) > old {
observed_concurrency.store(true, Ordering::Relaxed);
}
match *key {
KEY1 => 0,
KEY2 => 1,
_ => unreachable!(),
}
}
}));
let key1 = thread::spawn({
let fett = fett.clone();
move || {
assert_eq!(fett.get(KEY1), 0);
}
});
assert_eq!(fett.get(KEY2), 1);
key1.join().unwrap();
assert_eq!(counter.load(Ordering::Relaxed), 2);
assert_eq!(observed_concurrency.load(Ordering::Relaxed), false);
});
}