Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,104 @@
|
||||
// 独立 Tokio 参照补齐当前阻塞工作负载的收尾合同;不调用 Dever 运行库。
|
||||
// 原始轻量参照继续保留,不将本组结果冒充原参照的性能提升。
|
||||
use futures_util::FutureExt;
|
||||
use std::panic::{AssertUnwindSafe, catch_unwind};
|
||||
use tokio_util::task::TaskTracker;
|
||||
|
||||
impl NativeTasks {
|
||||
fn worker_scope<Value>(
|
||||
&self,
|
||||
call: impl AsyncFnOnce(&TaskTracker) -> Value,
|
||||
) -> Result<Value, Fault> {
|
||||
let tasks = TaskTracker::new();
|
||||
self.runtime.block_on(async {
|
||||
let result = AssertUnwindSafe(async { call(&tasks).await }).catch_unwind().await;
|
||||
tasks.close();
|
||||
tasks.wait().await;
|
||||
result.map_err(task_fault)
|
||||
})
|
||||
}
|
||||
|
||||
async fn tracked_blocking<Value: Send + 'static>(
|
||||
&self,
|
||||
tasks: &TaskTracker,
|
||||
call: impl FnOnce() -> Value + Send + 'static,
|
||||
) -> Result<Value, Fault> {
|
||||
if tasks.is_closed() {
|
||||
return Err(task_fault("closed worker scope"));
|
||||
}
|
||||
let permit = self.workers.clone().acquire_owned().await.unwrap();
|
||||
let token = tasks.token();
|
||||
let (result, _token) = tokio::task::spawn_blocking(move || {
|
||||
let _permit = permit;
|
||||
let result = catch_unwind(AssertUnwindSafe(call)).map_err(task_fault);
|
||||
// 输出先析构,跟踪才结束;panic 载荷也在通知排空前释放。
|
||||
(result, token)
|
||||
}).await.map_err(task_fault)?;
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
fn reference_worker_scoped<const BLOCKING: bool, const CALLS: usize>(
|
||||
values: &[TaskCase],
|
||||
) -> Result<i64, Fault> {
|
||||
if BLOCKING {
|
||||
reference_worker_calls::<CALLS, _>(values, |owned| {
|
||||
native_blocking_sleep(0)?;
|
||||
native_total(&owned).map_err(NativeAsyncFailure::from)
|
||||
})
|
||||
} else {
|
||||
reference_worker_calls::<CALLS, _>(values, |owned| native_total(&owned))
|
||||
}
|
||||
}
|
||||
|
||||
fn native_blocking_sleep(millis: i64) -> Result<(), NativeAsyncFailure> {
|
||||
let fail = |message: &str| NativeAsyncFailure::Sleep(message.to_owned(), task_fault("sleep"));
|
||||
let millis = u64::try_from(millis).map_err(|_| fail("sleep duration must be nonnegative"))?;
|
||||
let duration = Duration::from_millis(millis);
|
||||
std::time::Instant::now().checked_add(duration)
|
||||
.ok_or_else(|| fail("sleep deadline is out of range"))?;
|
||||
std::thread::sleep(duration);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// 保留实际业务错误及文本负载;不以填充字段强凑与生成代码相同的布局。
|
||||
fn reference_worker_calls<const CALLS: usize, Failure: From<Fault> + Into<Fault> + Send + 'static>(
|
||||
values: &[TaskCase],
|
||||
call: impl FnOnce(Vec<i64>) -> Result<i64, Failure> + Copy + Send + 'static,
|
||||
) -> Result<i64, Fault> {
|
||||
let Some(value) = values.first() else { return Ok(0); };
|
||||
value.native.worker_scope(async |tasks| {
|
||||
let mut total = 0i64;
|
||||
for _ in 0..CALLS {
|
||||
let owned = value.values.clone();
|
||||
let result = value.native.tracked_blocking(tasks, move || call(owned))
|
||||
.await.map_err(Failure::from)??;
|
||||
total = total.checked_add(result)
|
||||
.ok_or_else(|| Failure::from(task_fault("integer overflow")))?;
|
||||
}
|
||||
Ok::<_, Failure>(total)
|
||||
})?.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn worker_scoped(cases: &[TaskCase]) {
|
||||
let expected = native_total(&cases[0].values).unwrap();
|
||||
assert_eq!(reference_worker_scoped::<false, 1>(cases).unwrap(), expected);
|
||||
assert_eq!(reference_worker_scoped::<true, 1>(cases).unwrap(), expected);
|
||||
assert_eq!(reference_worker_scoped::<false, CONTINUOUS_CALLS>(cases).unwrap(), expected * CONTINUOUS_CALLS as i64);
|
||||
assert_eq!(reference_worker_scoped::<true, CONTINUOUS_CALLS>(cases).unwrap(), expected * CONTINUOUS_CALLS as i64);
|
||||
let failures = [TaskCase {
|
||||
generated: new_runtime(), native: NativeTasks::new(), values: vec![i64::MAX, 1],
|
||||
}];
|
||||
assert!(reference_worker_scoped::<false, 1>(&failures).is_err());
|
||||
assert!(reference_worker_scoped::<true, 1>(&failures).is_err());
|
||||
assert!(reference_worker_scoped::<false, CONTINUOUS_CALLS>(&failures).is_err());
|
||||
assert!(reference_worker_scoped::<true, CONTINUOUS_CALLS>(&failures).is_err());
|
||||
compare_named("task_parallel_scoped", cases, 500,
|
||||
generated_parallel, reference_worker_scoped::<false, 1>, |value| *value as u64, "rust_scoped");
|
||||
compare_named("task_blocking_scoped", cases, 500,
|
||||
generated_blocking, reference_worker_scoped::<true, 1>, |value| *value as u64, "rust_scoped");
|
||||
compare_named("task_parallel_scoped_steady", cases, 64,
|
||||
generated_worker_steady::<false>, reference_worker_scoped::<false, CONTINUOUS_CALLS>, |value| *value as u64, "rust_scoped");
|
||||
compare_named("task_blocking_scoped_steady", cases, 64,
|
||||
generated_worker_steady::<true>, reference_worker_scoped::<true, CONTINUOUS_CALLS>, |value| *value as u64, "rust_scoped");
|
||||
}
|
||||
Reference in new issue
Block a user