#![cfg(loom)]
use persistent_queue::{Builder, Durability, MemStore};
#[test]
fn capacity_handoff_has_no_lost_wakeup() {
loom::model(|| {
let (tx, rx) = Builder::new(MemStore::new()).capacity(1).open().unwrap();
tx.push(b"a").unwrap();
let producer = tx.clone();
let blocked = loom::thread::spawn(move || {
producer.push(b"b").unwrap(); });
let a = rx.reserve().unwrap().expect("first item is present");
assert_eq!(&*a, &b"a"[..]);
a.ack().unwrap();
blocked.join().unwrap();
let b = rx.reserve().unwrap().expect("second item is present");
assert_eq!(&*b, &b"b"[..]);
b.ack().unwrap();
});
}
#[test]
fn group_commit_flushes_every_producer() {
loom::model(|| {
let (tx, rx) = Builder::new(MemStore::new())
.capacity(8)
.durability(Durability::Group)
.open()
.unwrap();
let p1 = {
let tx = tx.clone();
loom::thread::spawn(move || tx.push(b"a").unwrap())
};
let p2 = {
let tx = tx.clone();
loom::thread::spawn(move || tx.push(b"b").unwrap())
};
p1.join().unwrap();
p2.join().unwrap();
let mut seen = 0;
while let Some(item) = rx.reserve().unwrap() {
item.ack().unwrap();
seen += 1;
}
assert_eq!(seen, 2);
});
}
#[test]
fn concurrent_producers_deliver_both_sync() {
loom::model(|| {
let (tx, rx) = Builder::new(MemStore::new()).capacity(4).open().unwrap();
let p1 = {
let tx = tx.clone();
loom::thread::spawn(move || tx.push(b"a").unwrap())
};
let p2 = {
let tx = tx.clone();
loom::thread::spawn(move || tx.push(b"b").unwrap())
};
let mut seen = 0;
let mut spins = 0;
while seen < 2 {
if let Some(item) = rx.reserve().unwrap() {
item.ack().unwrap();
seen += 1;
} else {
spins += 1;
assert!(spins < 1000, "an item was lost: the consumer starved");
loom::thread::yield_now();
}
}
p1.join().unwrap();
p2.join().unwrap();
});
}