curfew 0.0.5

A deadline-aware fork-join model where multiple tasks run in parallel, but only those that finish before a specified absolute clock time are joined and their results collected.
Documentation
#[cfg(feature = "tokio")]
use curfew::{
    join_with_deadline_async, DeadlineJoinerAsync, JoinOutcomeAsync,
    TaskOutcome,
};
#[cfg(feature = "tokio")]
use std::time::{Duration, Instant};

#[cfg(feature = "tokio")]
#[tokio::main(flavor = "current_thread")]
async fn main() {
    let deadline = Instant::now() + Duration::from_millis(200);
    let mut joiner = DeadlineJoinerAsync::new(deadline);

    for value in 0..4u32 {
        joiner.spawn(async move {
            tokio::time::sleep(Duration::from_millis(u64::from(
                40 * (value + 1),
            )))
            .await;
            format!("async-job-{value}")
        });
    }

    let summary = joiner.join_ready().await;
    println!("{} async tasks finished on time", summary.completed_count());
    println!("{} async tasks missed the deadline", summary.timed_out_count());

    for task in summary.completed {
        match task.outcome {
            TaskOutcome::Completed(value) => {
                println!("task {} => {}", task.task_id, value)
            }
            TaskOutcome::Panicked(info) => {
                println!("task {} panicked: {}", task.task_id, info)
            }
        }
    }

    if !summary.timed_out.is_empty() {
        println!(
            "still running: {:?}",
            summary.timed_out.iter().map(|t| t.task_id).collect::<Vec<_>>()
        );
    }

    let future = async {
        tokio::time::sleep(Duration::from_millis(250)).await;
        99
    };

    match join_with_deadline_async(
        future,
        Instant::now() + Duration::from_millis(80),
    )
    .await
    {
        JoinOutcomeAsync::Completed(result) => match result.outcome {
            TaskOutcome::Completed(value) => {
                println!("completed on time: {value}")
            }
            TaskOutcome::Panicked(info) => println!("future panicked: {info}"),
        },
        JoinOutcomeAsync::TimedOut(late) => {
            println!("future missed the deadline; awaiting late completion");
            let result = late.wait().await;
            println!("late outcome: {:?}", result.outcome);
        }
    }
}

#[cfg(not(feature = "tokio"))]
fn main() {
    eprintln!("Enable the `tokio` feature to run this example.");
}