YieldProgress

Struct YieldProgress 

Source
pub struct YieldProgress { /* private fields */ }
Expand description

Allows a long-running async task to report its progress, while also yielding to the scheduler (e.g. for single-threaded web environment) and introducing cancellation points.

These things go together because the rate at which it makes sense to yield (to avoid event loop hangs) is similar to the rate at which it makes sense to report progress.


To construct a YieldProgress, use the Builder, or noop().

Implementations§

Source§

impl YieldProgress

Source

pub fn noop() -> Self

Returns a YieldProgress that does no progress reporting and no yielding at all.

This may be used, for example, to call a function that accepts YieldProgress and is not async for any other reason. It should not be used merely because no progress reporting is desired; in that case use Builder instead so that a yield function can be provided.

§Example
let mut progress = YieldProgress::noop();
// These calls will have no effect.
progress.set_label("a tree falls in a forest");
progress.progress(0.12345).await;
Source

pub fn set_label(&mut self, label: impl Display)

Add a name for the portion of work this YieldProgress covers, which will be used by all future progress updates.

If there is already a label, it will be overwritten.

This does not immediately report progress; that is, the label will not be visible anywhere until the next operation that does. Future versions may report it immediately.

§Example
async fn process_things(progress: YieldProgress, things: &[String]) {
    let len = things.len();
    for ((mut progress, thing), i) in progress.split_evenly(len).zip(things).zip(1..) {
        progress.set_label(format_args!("Processing {i}/{len}: {thing}"));
        progress.progress(0.0).await;
        // ... Do actual work here ...
        progress.finish().await;
    }
}
Source

pub fn progress( &self, progress_fraction: f32, ) -> impl Future<Output = ()> + use<>

Report the current amount of progress (a number from 0 to 1) and yield.

The value may be less than previously given values.

§Example
async fn do_work(progress: YieldProgress) {
    first_half_of_work();
    progress.progress(0.5).await;
    second_half_of_work();
    progress.finish().await;
}
Source

pub fn progress_without_yield(&self, progress_fraction: f32)

Report the current amount of progress (a number from 0 to 1) without yielding.

Caution: Not yielding may mean that the display of progress to the user does not update. This should be used only when necessary for non-async code.

Source

pub fn yield_without_progress(&self) -> impl Future<Output = ()> + Send + use<>

Yield only; that is, call the yield function contained within this YieldProgress.

Source

pub fn finish(self) -> impl Future<Output = ()> + Send + use<>

Report that 100% of progress has been made.

This is identical to .progress(1.0) but consumes the YieldProgress object.

Source

pub fn finish_and_cut( self, progress_fraction: f32, ) -> impl Future<Output = Self> + Send + use<>

Report that the given amount of progress has been made, then return a YieldProgress covering the remaining range.

§Example
async fn do_work(progress: YieldProgress) {
    first_half_of_work();
    second_half_of_work(progress.finish_and_cut(0.5).await).await;
}
Source

pub fn start_and_cut( &mut self, cut: f32, label: impl Display, ) -> impl Future<Output = Self> + Send + 'static

Report the beginning of a unit of work of size progress_fraction and described by label. That fraction is cut off of the beginning range of self, and returned as a separate YieldProgress.

§Example
async fn do_work(mut progress: YieldProgress) {
    first_half_of_work(progress.start_and_cut(0.5, "first half").await).await;
    second_half_of_work();
    progress.finish().await;
}
Source

pub fn split(self, cut: f32) -> [Self; 2]

Construct two new YieldProgress which divide the progress value into two subranges.

The returned instances should be used in sequence, but this is not enforced. Using them concurrently will result in the progress bar jumping backwards.

§Example
async fn do_work(mut progress: YieldProgress) {
    let [p1, p2] = progress.split(0.5);
    first_half_of_work(p1).await;
    second_half_of_work(p2).await;
}
Source

pub fn split_evenly( self, count: usize, ) -> impl DoubleEndedIterator<Item = YieldProgress> + ExactSizeIterator + FusedIterator + use<>

Construct many new YieldProgress which together divide the progress value into count subranges.

The returned instances should be used in sequence, but this is not enforced. Using them concurrently will result in the progress bar jumping backwards.

§Example
async fn process_things(progress: YieldProgress, things: Vec<Thing>) {
    for (mut progress, thing) in progress.split_evenly(things.len()).zip(things) {
        process_one_thing(thing);
        progress.finish().await;
    }
}
Source

pub fn split_evenly_concurrent( self, count: usize, ) -> impl DoubleEndedIterator<Item = YieldProgress> + ExactSizeIterator + FusedIterator + use<>

Construct many new YieldProgress which will collectively advance self to completion when they have all been advanced to completion, and which may be used concurrently.

This is identical in effect to YieldProgress::split_evenly(), except that it comprehends concurrent operations — the progress of self is the sum of the progress of the subtasks. To support this, it must allocate storage for the state tracking and synchronization, and every progress update must calculate the sum from all subtasks. Therefore, for efficiency, do not use this except when concurrency is actually present.

The label passed through will be the label from the first subtask that has a progress value less than 1.0. This choice may be changed in the future if the label system is elaborated.

§Example
use yield_progress::YieldProgress;
use tokio::task::JoinSet;

async fn process_things(progress: YieldProgress, things: Vec<Thing>) {
    let mut join_set = tokio::task::JoinSet::new();
    for (mut progress, thing) in progress.split_evenly_concurrent(things.len()).zip(things) {
        join_set.spawn(process_one_thing(progress, thing));
    }
    join_set.join_all().await;
}

Trait Implementations§

Source§

impl Debug for YieldProgress

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.