Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,102 @@
|
||||
// 独立使用 Tokio 的取消与排空参照;不调用 Dever 的 Scope、Task 或生成函数。
|
||||
use tokio_util::task::{AbortOnDropHandle, task_tracker::TaskTrackerToken};
|
||||
|
||||
impl NativeTasks {
|
||||
fn tracked_leaf<Value, Work>(
|
||||
&self,
|
||||
tasks: &TaskTracker,
|
||||
call: impl FnOnce() -> Work + Send + 'static,
|
||||
) -> Result<AbortOnDropHandle<(Value, TaskTrackerToken)>, Fault>
|
||||
where
|
||||
Value: Send + 'static,
|
||||
Work: std::future::Future<Output = Value> + Send + 'static,
|
||||
{
|
||||
if tasks.is_closed() {
|
||||
return Err(task_fault("closed task scope"));
|
||||
}
|
||||
let permit = self.tasks.clone().try_acquire_owned().map_err(task_fault)?;
|
||||
let tracking = tasks.token();
|
||||
let future = async move {
|
||||
let result = call().await;
|
||||
drop(permit);
|
||||
result
|
||||
};
|
||||
// Future 先释放;未领取的输出也必须先于跟踪令牌释放。
|
||||
Ok(AbortOnDropHandle::new(tokio::spawn(
|
||||
future.map(move |result| (result, tracking)),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn reference_cancel_scoped(values: &[TaskCase]) -> Result<i64, Fault> {
|
||||
let Some(value) = values.first() else { return Ok(0); };
|
||||
value.native.worker_scope(async |tasks| {
|
||||
let task = value.native.tracked_leaf(tasks, || native_fallible_sleep(60000))?;
|
||||
task.abort();
|
||||
match task.await {
|
||||
Err(error) if error.is_cancelled() => (),
|
||||
Err(error) => return Err(NativeAsyncFailure::Fault(task_fault(error))),
|
||||
Ok((result, _tracking)) => result?,
|
||||
}
|
||||
Ok::<_, NativeAsyncFailure>(1)
|
||||
})?.map_err(Into::into)
|
||||
}
|
||||
|
||||
fn cancel_scoped(cases: &[TaskCase]) {
|
||||
compare_named("task_cancel_scoped", cases, 1000,
|
||||
generated_cancel, reference_cancel_scoped, |value| *value as u64, "rust_scoped");
|
||||
}
|
||||
|
||||
fn check_cancel_cleanup() {
|
||||
let native = NativeTasks::new();
|
||||
native.worker_scope(async |tasks| {
|
||||
let task = native.tracked_leaf(tasks, || async { 42 }).unwrap();
|
||||
let (value, tracking) = task.await.unwrap();
|
||||
assert_eq!(value, 42);
|
||||
drop(tracking);
|
||||
let permits = native.tasks.clone().acquire_many_owned(8).await.unwrap();
|
||||
assert!(native.tracked_leaf(tasks, || async {}).is_err());
|
||||
drop(permits);
|
||||
tasks.close();
|
||||
assert!(native.tracked_leaf(tasks, || async {}).is_err());
|
||||
}).unwrap();
|
||||
|
||||
// 立即放弃、已启动 Future、未领取输出分别验证,根 panic 也必须排空。
|
||||
for stage in 0..3 {
|
||||
for root_panics in [false, true] {
|
||||
let dropped = Arc::new(AtomicBool::new(false));
|
||||
let observed = dropped.clone();
|
||||
let owned = WorkerOutput(dropped);
|
||||
let outcome = native.worker_scope(async |tasks| {
|
||||
let (started, ready) = tokio::sync::oneshot::channel();
|
||||
let task = native.tracked_leaf(tasks, move || async move {
|
||||
if stage != 0 { started.send(()).unwrap(); }
|
||||
if stage != 2 { std::future::pending::<()>().await; }
|
||||
owned
|
||||
}).unwrap();
|
||||
if stage != 0 { ready.await.unwrap(); }
|
||||
if stage == 2 {
|
||||
while !task.is_finished() { tokio::task::yield_now().await; }
|
||||
assert!(!observed.load(Ordering::SeqCst));
|
||||
}
|
||||
if root_panics { panic!("root failure after leaf submission"); }
|
||||
drop(task);
|
||||
});
|
||||
assert_eq!(outcome.is_err(), root_panics);
|
||||
assert!(observed.load(Ordering::SeqCst));
|
||||
assert_eq!(native.tasks.available_permits(), 8);
|
||||
}
|
||||
}
|
||||
|
||||
native.worker_scope(async |tasks| {
|
||||
let task = native.tracked_leaf(tasks, || async { Err::<(), _>("business failure") }).unwrap();
|
||||
while !task.is_finished() { tokio::task::yield_now().await; }
|
||||
task.abort();
|
||||
let (result, tracking) = task.await.unwrap();
|
||||
assert_eq!(result, Err("business failure"));
|
||||
drop(tracking);
|
||||
let task = native.tracked_leaf(tasks, || async { panic!("leaf failure") }).unwrap();
|
||||
assert!(task.await.unwrap_err().is_panic());
|
||||
}).unwrap();
|
||||
println!("leaf cleanup: capacity, closed scope, inputs, future, unclaimed output, root panic, business error, task panic and re-entry passed");
|
||||
}
|
||||
Reference in new issue
Block a user