async_nursery 0.5.0

Primitive for structured concurrency
Documentation
//! Run a number of tasks concurrently that each advance at their own speed and are assigned
//! a random number of jobs to process.
//!
//! Shows a progress bar of the number of jobs done.
//!
//! Expected output:
//!
//! $ cargo run --example return_progress
//!
//! ███████████████████████████████████████████████████████████████████████████████████████████████████▏1000/1000 jobs done.
//!
mod common;

use
{
	async_executors :: { AsyncStd                                                  } ,
	async_nursery   :: { Nursery, NurseExt                                         } ,
	common          :: { DynResult                                                 } ,
	futures         :: { StreamExt, future::ready                                  } ,
	futures_timer   :: { Delay                                                     } ,
	indicatif       :: { ProgressBar, ProgressStyle                                } ,
	rand            :: { distributions::{ Distribution, Uniform }, Rng, thread_rng } ,
	std             :: { time::Duration                                            } ,
};



async fn task( units_of_work: u64 ) -> u64
{
	let speed = thread_rng().gen_range( 10..1000 );
	Delay::new( Duration::from_millis( units_of_work*speed ) ).await;

	units_of_work
}



#[ async_std::main ]
//
async fn main() -> DynResult<()>
{
	const UNITS: u64 = 1000;
	let between   = Uniform::from( 1..=10 );
	let mut rng   = rand::thread_rng();
	let mut pool  = UNITS;
	let mut units_of_work;

	let (nursery, output) = Nursery::new( AsyncStd );

	while pool != 0
	{
		units_of_work = if pool <= 10 { pool } else { between.sample(&mut rng) };

		nursery.nurse( task(units_of_work) )?;
		pool -= units_of_work;
	}

	let pb = ProgressBar::new( UNITS );

	pb.set_style
	(
		ProgressStyle::default_bar()

			.template( "{prefix:.bold}▕{wide_bar:.green}▏{msg}" )
	);

	// don't forget.
	//
	drop(nursery);

	output.for_each( |x|
	{
		pb.inc(x);
		pb.set_message( format!( "{}/{} jobs done.", pb.position(), UNITS ) );
		ready(())

	}).await;


	pb.finish();

	Ok(())
}