use std::time; use context_async::{Context, Timer}; /// In this example, we spawn a few context from a root context, and show how `cancel` works. async fn a_very_heavy_task() { tokio::time::sleep(tokio::time::Duration::from_secs(100)).await; } #[tokio::main] async fn main() { // our job should finish in 10 seconds. let root = Timer::with_timeout(tokio::time::Duration::from_secs(10)); let root2 = root.clone(); // clone a context (same as root). let root_job = tokio::spawn(async move { let result = root2.handle(a_very_heavy_task()).await; println!("root2 result: {:?}", result); }); let t1 = root.spawn().await; // spawn a child context. let t1_to_cancel = t1.clone(); // t1 will be moved, so the clone it for cancel. let t11 = t1.spawn_with_timeout(time::Duration::from_secs(5)).await; // spawn a child context of t1. let t11_to_cancel = t11.clone(); let j1 = tokio::spawn(async move { let result = t1.handle(a_very_heavy_task()).await; println!("t1 result: {:?}", result); }); let j11 = tokio::spawn(async move { let result = t11.handle(a_very_heavy_task()).await; println!("t11 result: {:?}", result); }); // if we cancel t1, then t11 (the child of t1) would be cancelled at the same time. t1_to_cancel.cancel().await; // it would print that t1 and t11 `ContextCancelled`. assert!(t1_to_cancel.is_cancelled().await); assert!(t11_to_cancel.is_cancelled().await); // but this would NOT affect root, because root is the parent of t1. assert!( ! root.is_cancelled().await ); root_job.await.unwrap(); j1.await.unwrap(); j11.await.unwrap(); // the root job will end with error `ContextTimeout` after 10s. // STDOUT: // t1 result: Err(ContextCancelled) // t11 result: Err(ContextCancelled) // root2 result: Err(ContextTimeout) }