use dtact::dta_scheduler::{Mailbox, TaskChunk, Warehouse};
use dtact::memory_management::{ContextPool, FiberContext, FiberStatus, SafetyLevel};
use loom::sync::Arc;
use loom::sync::atomic::Ordering;
use loom::thread;
fn bounded_model<F: Fn() + Sync + Send + 'static>(f: F) {
let mut builder = loom::model::Builder::new();
builder.preemption_bound = Some(2);
builder.max_branches = 10_000;
builder.check(f);
}
#[cfg_attr(miri, ignore)]
#[test]
fn test_production_fiber_state_transitions() {
loom::model(|| {
let ctx = Arc::new(FiberContext::new());
ctx.state
.store(FiberStatus::Running as u32, Ordering::Release);
let ctx_clone = ctx.clone();
let waker = thread::spawn(move || {
let prev = ctx_clone
.state
.swap(FiberStatus::Notified as u32, Ordering::AcqRel);
if prev == FiberStatus::Yielded as u32 {
}
});
let waiter = thread::spawn(move || {
let cur_state = ctx.state.load(Ordering::Acquire);
if cur_state != FiberStatus::Running as u32 {
ctx.state
.store(FiberStatus::Running as u32, Ordering::Release);
}
if ctx
.state
.compare_exchange(
FiberStatus::Running as u32,
FiberStatus::Suspending as u32,
Ordering::Release,
Ordering::Acquire,
)
.is_ok()
{
}
});
waker.join().unwrap();
waiter.join().unwrap();
});
}
#[cfg_attr(miri, ignore)]
#[test]
fn test_production_context_pool_alloc_free() {
bounded_model(|| {
let pool = Arc::new(ContextPool::new(2, 8192, SafetyLevel::Safety0, 0).expect("pool init"));
let p1 = pool.clone();
let t1 = thread::spawn(move || {
if let Some(idx) = p1.alloc_context() {
p1.free_context(idx);
}
});
let p2 = pool.clone();
let t2 = thread::spawn(move || {
if let Some(idx) = p2.alloc_context() {
p2.free_context(idx);
}
});
t1.join().unwrap();
t2.join().unwrap();
});
}
#[cfg_attr(miri, ignore)]
#[test]
fn test_production_mailbox_spsc() {
loom::model(|| {
let mailbox = Arc::new(Mailbox::new());
let m1 = mailbox.clone();
let producer = thread::spawn(move || {
let chunk = TaskChunk::default();
let _ = m1.push(chunk);
});
let m2 = mailbox.clone();
let consumer = thread::spawn(move || {
let _ = m2.pop();
});
producer.join().unwrap();
consumer.join().unwrap();
});
}
#[cfg_attr(miri, ignore)]
#[test]
fn test_production_warehouse_mpmc() {
bounded_model(|| {
let warehouse = Arc::new(Warehouse::new());
let w1 = warehouse.clone();
let producer = thread::spawn(move || {
let chunk = TaskChunk::default();
let _ = w1.push(chunk);
});
let w2 = warehouse.clone();
let consumer = thread::spawn(move || {
let _ = w2.pop();
});
producer.join().unwrap();
consumer.join().unwrap();
});
}
#[cfg_attr(miri, ignore)]
#[test]
fn test_production_warehouse_two_producers() {
bounded_model(|| {
let warehouse = Arc::new(Warehouse::new());
let w1 = warehouse.clone();
let p1 = thread::spawn(move || {
let _ = w1.push(TaskChunk::default());
});
let w2 = warehouse.clone();
let p2 = thread::spawn(move || {
let _ = w2.push(TaskChunk::default());
});
let w3 = warehouse.clone();
let c1 = thread::spawn(move || {
let _ = w3.pop();
});
p1.join().unwrap();
p2.join().unwrap();
c1.join().unwrap();
});
}