// 调度器保持存活,计时包含输入复制、提交、结果领取和作用域清理。 // 独立参照针对同样的一层双任务/worker/计时器,不能代表任意嵌套并发已验收。 use dever_runtime::task::{Limits, Runtime}; struct TaskCase { generated: Runtime, native: NativeTasks, values: Vec, } fn new_runtime() -> Runtime { Runtime::new(Limits { threads: 2, workers: 2, tasks: 8, }) .unwrap() } fn generated_sync(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value .generated .run(async |scope| { GENERATED_SYNC(&value.values, scope).await }) .map_err(task_fault)? .map_err(task_fault) } fn reference_sync(values: &[TaskCase]) -> Result { values .first() .map_or(Ok(0), |value| value.native.pair(&value.values, false)) } fn generated_async(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value .generated .run(async |scope| { GENERATED_ASYNC(&value.values, scope).await }) .map_err(task_fault)? .map_err(task_fault) } fn reference_async(values: &[TaskCase]) -> Result { values .first() .map_or(Ok(0), |value| value.native.pair(&value.values, true)) } fn generated_parallel(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value .generated .run(async |scope| { GENERATED_PARALLEL(&value.values, scope).await }) .map_err(task_fault)? .map_err(task_fault) } fn reference_parallel(values: &[TaskCase]) -> Result { values .first() .map_or(Ok(0), |value| value.native.blocking(&value.values, false)) } fn generated_blocking(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value .generated .run(async |scope| { GENERATED_BLOCKING(&value.values, scope).await }) .map_err(task_fault)? .map_err(task_fault) } fn reference_blocking(values: &[TaskCase]) -> Result { values .first() .map_or(Ok(0), |value| value.native.blocking(&value.values, true)) } fn generated_cancel(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value .generated .run(async |scope| { GENERATED_CANCEL(scope).await }) .map_err(task_fault)? .map_err(task_fault) } fn reference_cancel(values: &[TaskCase]) -> Result { values.first().map_or(Ok(0), |value| value.native.cancel()) } fn generated_timer(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value .generated .run_leaf(GENERATED_TIMER()) .map_err(task_fault)? .map_err(task_fault) } fn reference_timer(values: &[TaskCase]) -> Result { values.first().map_or(Ok(0), |value| value.native.timer()) } fn generated_fault(values: &[TaskCase]) -> Result { Ok(generated_sync(values).is_err()) } fn reference_fault(values: &[TaskCase]) -> Result { Ok(reference_sync(values).is_err()) } fn main() { if std::env::args().any(|argument| argument == "--check-cancel-cleanup") { check_cancel_cleanup(); return; } if std::env::args().any(|argument| argument == "--check-worker-cleanup") { check_worker_cleanup(); return; } let cases = [TaskCase { generated: new_runtime(), native: NativeTasks::new(), values: (0..128).collect(), }]; let expected = native_total(&cases[0].values).unwrap(); assert_eq!(generated_sync(&cases).unwrap(), expected * 2); assert_eq!(generated_async(&cases).unwrap(), expected * 2); assert_eq!(generated_parallel(&cases).unwrap(), expected); assert_eq!(generated_blocking(&cases).unwrap(), expected); assert_eq!(generated_cancel(&cases).unwrap(), 1); println!("case,sample,implementation,elapsed_ns,checksum"); compare( "task_sync_pair", &cases, 500, generated_sync, reference_sync, |value| *value as u64, ); compare( "task_async_pair", &cases, 1000, generated_async, reference_async, |value| *value as u64, ); compare( "task_parallel", &cases, 500, generated_parallel, reference_parallel, |value| *value as u64, ); compare( "task_blocking", &cases, 500, generated_blocking, reference_blocking, |value| *value as u64, ); compare( "task_cancel", &cases, 1000, generated_cancel, reference_cancel, |value| *value as u64, ); compare( "task_timer_zero", &cases, 10, generated_timer, reference_timer, |value| *value as u64, ); let failures = [TaskCase { generated: new_runtime(), native: NativeTasks::new(), values: vec![i64::MAX, 1], }]; assert!(generated_fault(&failures).unwrap()); assert!(generated_async(&failures).is_err()); assert!(reference_async(&failures).is_err()); assert!(shared_async(&failures).is_err()); assert!(shared_worker::(&failures).is_err()); assert!(shared_worker::(&failures).is_err()); assert!(generated_nested(&failures).is_err()); assert!(reference_nested(&failures).is_err()); compare( "task_sync_fault", &failures, 500, generated_fault, reference_fault, |value| u64::from(*value), ); assert!(generated_async_steady(&failures).is_err()); assert!(reference_async_steady(&failures).is_err()); assert!(reference_async_tracked(&failures).is_err()); assert!(reference_async_typed(&failures).is_err()); drop(failures); lifecycle(&cases); shared_runtime(&cases); worker_steady(&cases); worker_scoped(&cases); cancel_scoped(&cases); }