#[cfg(not(feature = "loom"))]
mod loom {
pub use std::thread;
pub use std::sync;
pub fn model<F>(f: F)
where
F: Fn() + Sync + Send + 'static
{
f()
}
}
use std::num::NonZeroUsize;
use loom::sync::Arc;
use loom::thread;
use wfqueue::queue::{ WfQueue, EnqueueCtx, DequeueCtx };
#[test]
fn one_thread() {
loom::model(|| {
let queue = WfQueue::new(3);
let mut ecx = EnqueueCtx::new();
let mut dcx = DequeueCtx::new();
let val = NonZeroUsize::new(0x42).unwrap();
assert!(queue.try_enqueue(&mut ecx, val));
let val2 = queue.try_dequeue(&mut dcx).unwrap();
assert_eq!(val, val2);
assert!(queue.try_dequeue(&mut dcx).is_none());
assert!(queue.is_empty());
let valx = NonZeroUsize::new(0x42).unwrap();
let valy = NonZeroUsize::new(0x43).unwrap();
let valz = NonZeroUsize::new(0x44).unwrap();
assert!(queue.try_enqueue(&mut ecx, valx));
assert!(queue.try_enqueue(&mut ecx, valy));
assert!(queue.try_enqueue(&mut ecx, valz));
assert!(!queue.try_enqueue(&mut ecx, valz));
assert!(queue.is_full());
let valx2 = queue.try_dequeue(&mut dcx).unwrap();
let valy2 = queue.try_dequeue(&mut dcx).unwrap();
let valz2 = queue.try_dequeue(&mut dcx).unwrap();
assert_eq!(valx, valx2);
assert_eq!(valy, valy2);
assert_eq!(valz, valz2);
});
}
#[test]
fn two_thread() {
loom::model(|| {
let queue = Arc::new(WfQueue::new(3));
let queue2 = queue.clone();
let h = thread::spawn(move || {
let mut ecx = EnqueueCtx::new();
for i in 0..5 {
let val = NonZeroUsize::new(0x42 + i).unwrap();
while !queue2.try_enqueue(&mut ecx, val) {
loom::sync::atomic::spin_loop_hint();
}
}
});
let mut dcx = DequeueCtx::new();
for i in 0..5 {
let val = NonZeroUsize::new(0x42 + i).unwrap();
loop {
if let Some(val2) = queue.try_dequeue(&mut dcx) {
assert_eq!(val, val2);
break
}
loom::sync::atomic::spin_loop_hint();
}
}
h.join().unwrap();
});
}
#[test]
fn three_thread_s2r1() {
loom::model(|| {
let queue = Arc::new(WfQueue::new(3));
let queue2 = queue.clone();
let queue3 = queue.clone();
let h = thread::spawn(move || {
let mut ecx = EnqueueCtx::new();
for i in 0..2 {
let val = NonZeroUsize::new(0x42 + i).unwrap();
while !queue2.try_enqueue(&mut ecx, val) {
loom::sync::atomic::spin_loop_hint();
}
}
});
let h2 = thread::spawn(move || {
let mut ecx = EnqueueCtx::new();
for i in 2..4 {
let val = NonZeroUsize::new(0x42 + i).unwrap();
while !queue3.try_enqueue(&mut ecx, val) {
loom::sync::atomic::spin_loop_hint();
}
}
});
let mut dcx = DequeueCtx::new();
let mut output = Vec::new();
for _ in 0..4 {
loop {
if let Some(val) = queue.try_dequeue(&mut dcx) {
output.push(val.get());
break
}
loom::sync::atomic::spin_loop_hint();
}
}
h.join().unwrap();
h2.join().unwrap();
output.sort();
let expected = (0..4).map(|n| 0x42 + n).collect::<Vec<usize>>();
assert_eq!(expected, output.as_slice());
});
}
#[test]
fn three_thread_s1r2() {
loom::model(|| {
let queue = Arc::new(WfQueue::new(3));
let queue2 = queue.clone();
let queue3 = queue.clone();
let h = thread::spawn(move || {
let mut ecx = EnqueueCtx::new();
for i in 0..4 {
let val = NonZeroUsize::new(0x42 + i).unwrap();
while !queue2.try_enqueue(&mut ecx, val) {
loom::sync::atomic::spin_loop_hint();
}
}
});
let h2 = thread::spawn(move || {
let mut dcx = DequeueCtx::new();
let mut output = Vec::new();
for _ in 0..2 {
loop {
if let Some(val) = queue3.try_dequeue(&mut dcx) {
output.push(val.get());
break
}
loom::sync::atomic::spin_loop_hint();
}
}
output
});
let mut dcx = DequeueCtx::new();
let mut output = Vec::new();
for _ in 0..2 {
loop {
if let Some(val) = queue.try_dequeue(&mut dcx) {
output.push(val.get());
break
}
loom::sync::atomic::spin_loop_hint();
}
}
h.join().unwrap();
let mut output2 = h2.join().unwrap();
output.append(&mut output2);
output.sort();
let expected = (0..4).map(|n| 0x42 + n).collect::<Vec<usize>>();
assert_eq!(expected, output.as_slice());
});
}