Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,76 @@
|
||||
// 只由显式检查入口运行;同步通道控制 worker 时点,不用睡眠猜测退出顺序。
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
struct WorkerOutput(Arc<AtomicBool>);
|
||||
|
||||
impl Drop for WorkerOutput {
|
||||
fn drop(&mut self) {
|
||||
self.0.store(true, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_worker_cleanup() {
|
||||
assert!(matches!(native_blocking_sleep(-1), Err(NativeAsyncFailure::Sleep(message, _))
|
||||
if message == "sleep duration must be nonnegative"));
|
||||
let native = NativeTasks::new();
|
||||
native.worker_scope(async |tasks| {
|
||||
assert_eq!(native.tracked_blocking(tasks, || 42).await.unwrap(), 42);
|
||||
let failure = native.tracked_blocking(tasks, || Err::<(), _>("business failure")).await;
|
||||
assert_eq!(failure.unwrap(), Err("business failure"));
|
||||
tasks.close();
|
||||
assert!(native.tracked_blocking(tasks, || panic!("closed scope ran work")).await.is_err());
|
||||
}).unwrap();
|
||||
|
||||
let called = Arc::new(AtomicBool::new(false));
|
||||
native.worker_scope(async |tasks| {
|
||||
let permits = native.workers.clone().acquire_many_owned(2).await.unwrap();
|
||||
let observed = called.clone();
|
||||
let queued = native.tracked_blocking(tasks, move || observed.store(true, Ordering::SeqCst));
|
||||
let mut queued = Box::pin(queued);
|
||||
assert!(futures_util::poll!(queued.as_mut()).is_pending());
|
||||
drop(queued);
|
||||
drop(permits);
|
||||
}).unwrap();
|
||||
assert!(!called.load(Ordering::SeqCst));
|
||||
|
||||
// 调用者取消、worker panic、根入口 panic 都必须排空真实工作和未领取结果。
|
||||
for worker_panics in [false, true] {
|
||||
for root_panics in [false, true] {
|
||||
let dropped = Arc::new(AtomicBool::new(false));
|
||||
let observed = dropped.clone();
|
||||
let (release, blocked) = std::sync::mpsc::channel();
|
||||
let (started, ready) = tokio::sync::oneshot::channel();
|
||||
let worker = move || {
|
||||
started.send(()).unwrap();
|
||||
blocked.recv_timeout(Duration::from_secs(2)).unwrap();
|
||||
let output = WorkerOutput(dropped);
|
||||
if worker_panics { std::panic::panic_any(output); }
|
||||
output
|
||||
};
|
||||
let result = native.worker_scope(async |tasks| {
|
||||
let mut pending = Box::pin(native.tracked_blocking(tasks, worker));
|
||||
assert!(futures_util::poll!(pending.as_mut()).is_pending());
|
||||
ready.await.unwrap();
|
||||
drop(pending);
|
||||
assert_eq!(native.workers.available_permits(), 1);
|
||||
assert!(!tasks.is_empty());
|
||||
assert!(!observed.load(Ordering::SeqCst));
|
||||
release.send(()).unwrap();
|
||||
if root_panics { panic!("root failure after worker submission"); }
|
||||
});
|
||||
assert_eq!(result.is_err(), root_panics);
|
||||
assert!(observed.load(Ordering::SeqCst));
|
||||
assert_eq!(native.workers.available_permits(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
let claimed = native.worker_scope(async |tasks| {
|
||||
let result = native.tracked_blocking(tasks, || String::from("owned output")).await.unwrap();
|
||||
tasks.close();
|
||||
tasks.wait().await;
|
||||
result
|
||||
}).unwrap();
|
||||
assert_eq!(claimed, "owned output");
|
||||
assert_eq!(native.worker_scope(async |tasks| native.tracked_blocking(tasks, || 7).await).unwrap().unwrap(), 7);
|
||||
println!("worker cleanup: success, business error, closed scope, queued cancellation, running cancellation, panic, result drop and re-entry passed");
|
||||
}
|
||||
Reference in new issue
Block a user