task_scope 0.1.1

asynchronous runtime extension for supporting Structured Concurrency with task spawning
Documentation
use futures::future::FutureExt;
use futures::{pin_mut, select};
use std::time::Duration;
use tokio::signal::ctrl_c;
use tokio::time::delay_for;

use task_scope::{cancelable, scope, spawn, Canceled};

#[tokio::main]
async fn main() {
    let scope = scope(async {
        // nesting scopes. if you gracefully cancel outer scope, cancellation will be propagated to inner scopes
        spawn(scope(async {
            println!("doing a heavy task");

            let result = cancelable(delay_for(Duration::from_secs(5))).await;

            match result {
                Err(Canceled::Graceful) => {
                    println!("graceful cancellation is requested");

                    // this scope will wait until cancellation finishes
                    delay_for(Duration::from_secs(1)).await;

                    println!("cancellation is done");
                }
                Err(Canceled::Forced) => {
                    // now, the task is in "mercy" period. we should exit immediately
                    println!("forced cancellation");
                }
                Ok(_) => println!("task is done"),
            }
        }))
        .await;

        42
    });
    pin_mut!(scope);

    let mut canceled = false;

    loop {
        select! {
            () = ctrl_c().fuse().map(Result::unwrap) => if canceled {
                println!("force quit");
                break;
            } else {
                println!("canceling... (Ctrl-C to force quit)");
                scope.as_mut().cancel();
                canceled = true;
            },
            result = scope.as_mut() => {
                match result {
                    Ok(v) => println!("scope finished: {}", v),
                    Err(e) => println!("scope canceled: {:?}", e),
                }
                break;
            },
        }
    }
}