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.
Note that while a YieldProgress
is Send
and Sync
in order to be used within tasks
that may be moved between threads, it does not currently support meaningfully being used from
multiple threads or futures at once — only within a fully sequential operation. Future versions
may include a “parallel split” operation but the current one does not.
To construct a YieldProgress
, use the Builder
, or noop()
.
Implementations§
Source§impl YieldProgress
impl YieldProgress
Sourcepub fn new<Y, YFut, P>(yielder: Y, progressor: P) -> Self
👎Deprecated: use yield_progress::Builder
instead
pub fn new<Y, YFut, P>(yielder: Y, progressor: P) -> Self
yield_progress::Builder
insteadConstruct a new YieldProgress
, which will call yielder
to yield and
progressor
to report progress.
yielder
should return aFuture
that returnsPoll::Pending
at least once, and may perform other executor-specific actions to assist with scheduling other tasks.progressor
is called with the progress fraction (a number between 0 and 1) and a label for the current portion of work (which will be""
if no label has been set).
§Example
use yield_progress::YieldProgress;
// let some_progress_bar = ...;
let progress = YieldProgress::new(
tokio::task::yield_now,
move |fraction, _label| {
some_progress_bar.set_value(fraction);
}
);
Sourcepub fn noop() -> Self
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
use yield_progress::YieldProgress;
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;
Sourcepub fn set_label(&mut self, label: impl Display)
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.
Sourcepub fn progress(
&self,
progress_fraction: f32,
) -> impl Future<Output = ()> + Send + 'static
pub fn progress( &self, progress_fraction: f32, ) -> impl Future<Output = ()> + Send + 'static
Report the current amount of progress (a number from 0 to 1) and yield.
The value may be less than previously given values.
Sourcepub fn progress_without_yield(&self, progress_fraction: f32)
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.
Sourcepub fn yield_without_progress(
&self,
) -> impl Future<Output = ()> + Send + 'static
pub fn yield_without_progress( &self, ) -> impl Future<Output = ()> + Send + 'static
Yield only; that is, call the yield function contained within this YieldProgress
.
Sourcepub fn finish(self) -> impl Future<Output = ()> + Send + 'static
pub fn finish(self) -> impl Future<Output = ()> + Send + 'static
Report that 100% of progress has been made.
This is identical to .progress(1.0)
but consumes the YieldProgress
object.
Sourcepub fn finish_and_cut(
self,
progress_fraction: f32,
) -> impl Future<Output = Self> + Send + 'static
pub fn finish_and_cut( self, progress_fraction: f32, ) -> impl Future<Output = Self> + Send + 'static
Report that the given amount of progress has been made, then return
a YieldProgress
covering the remaining range.
Sourcepub fn start_and_cut(
&mut self,
cut: f32,
label: impl Display,
) -> impl Future<Output = Self> + Send + 'static
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
.
let a_progress = main_progress.start_and_cut(0.5, "task A").await;
// do task A...
a_progress.finish().await;
// continue using main_progress...
Sourcepub fn split(self, cut: f32) -> [Self; 2]
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.
Sourcepub fn split_evenly(
self,
count: usize,
) -> impl DoubleEndedIterator<Item = YieldProgress> + ExactSizeIterator + FusedIterator
pub fn split_evenly( self, count: usize, ) -> impl DoubleEndedIterator<Item = YieldProgress> + ExactSizeIterator + FusedIterator
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.
Sourcepub fn split_evenly_concurrent(
self,
count: usize,
) -> impl DoubleEndedIterator<Item = YieldProgress> + ExactSizeIterator + FusedIterator
pub fn split_evenly_concurrent( self, count: usize, ) -> impl DoubleEndedIterator<Item = YieldProgress> + ExactSizeIterator + FusedIterator
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.