// 手写 Rust 与 Dever 生成代码使用同一个运行时,隔离生成代码与运行时策略的成本。 // 原始直接 Tokio 参照继续保留;这里不调用任何生成函数或填充错误布局。 use dever_runtime::task::Scope; async fn handwritten_pair(scope: &Scope<'_>, values: &[i64]) -> Result { let first_values = values.to_vec(); let first = scope .spawn_leaf(move || native_async_total(first_values, false)) .map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))?; let second_values = values.to_vec(); let second = match scope.spawn_leaf(move || native_async_total(second_values, false)) { Ok(task) => task, Err(error) => { first.cancel(); let _ = first.wait().await; return Err(task_fault(error).into()); } }; let first = first.wait().await .map_err(|error| NativeAsyncFailure::Fault(task_fault(error))) .and_then(|result| result); if first.is_err() { second.cancel(); } let second = second.wait().await .map_err(|error| NativeAsyncFailure::Fault(task_fault(error))) .and_then(|result| result); first?.checked_add(second?) .ok_or_else(|| task_fault("integer overflow").into()) } async fn handwritten_cancel(scope: &Scope<'_>) -> Result { let task = scope.spawn_leaf(|| native_fallible_sleep(60000)) .map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))?; if let Some(result) = task.stop().await .map_err(|error| NativeAsyncFailure::Fault(task_fault(error)))? { result?; } Ok(1) } fn shared_async(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value.generated.run(async |scope| handwritten_pair(scope, &value.values).await) .map_err(task_fault)?.map_err(Into::into) } fn shared_cancel(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value.generated.run(async |scope| handwritten_cancel(scope).await) .map_err(task_fault)?.map_err(Into::into) } fn shared_worker(values: &[TaskCase]) -> Result { let Some(value) = values.first() else { return Ok(0); }; value.generated.run(async |scope| { let owned = value.values.clone(); scope.blocking(move || { if SLEEP { std::time::Instant::now() .checked_add(std::time::Duration::ZERO) .ok_or_else(|| task_fault("sleep deadline"))?; std::thread::sleep(std::time::Duration::ZERO); } native_total(&owned) }).await.map_err(task_fault)? }).map_err(task_fault)? } // 两侧都在真实父任务中执行双子任务;同样复制输入,不改用更大的错误或状态。 fn nested( values: &[TaskCase], call: impl FnOnce(Scope<'static>, Vec) -> Work + Send + 'static, ) -> Result where Work: std::future::Future> + Send + 'static, { let Some(value) = values.first() else { return Ok(0); }; let owned = value.values.clone(); value.generated.run(async move |scope| { let parent = scope.spawn(move |child| call(child, owned)).map_err(task_fault)?; parent.wait().await.map_err(task_fault)? }).map_err(task_fault)? } fn generated_nested(values: &[TaskCase]) -> Result { nested(values, |scope, owned| async move { GENERATED_ASYNC(&owned, &scope).await.map_err(task_fault) }) } fn reference_nested(values: &[TaskCase]) -> Result { nested(values, |scope, owned| async move { handwritten_pair(&scope, &owned).await.map_err(Into::into) }) } fn shared_runtime(cases: &[TaskCase]) { compare_named( "task_parallel_shared_runtime", cases, 500, generated_parallel, shared_worker::, |value| *value as u64, "rust_runtime", ); compare_named( "task_blocking_shared_runtime", cases, 500, generated_blocking, shared_worker::, |value| *value as u64, "rust_runtime", ); compare_named( "task_async_shared_runtime", cases, 1000, generated_async, shared_async, |value| *value as u64, "rust_runtime", ); compare_named( "task_cancel_shared_runtime", cases, 1000, generated_cancel, shared_cancel, |value| *value as u64, "rust_runtime", ); compare_named( "task_nested_shared_runtime", cases, 1000, generated_nested, reference_nested, |value| *value as u64, "rust_runtime", ); }