Expand description
A simple asynchronous task model for execution that needs to be started, stopped, mutated, and inspected.
§Worker cancellation
TaskControl requests cancellation for stop, inspection, and updates.
Return Err(Cancelled) to hand control back with unfinished work; Ok(())
means the worker is permanently finished until removed and reinserted.
An await need not return Pending. If a wrapped loop keeps making progress
in one poll, StopTask::until_stopped cannot interrupt it from outside.
Choose the wrapping style below to match your work loop. In both examples,
process is a bounded synchronous step.
§Per-operation waits
Wrap each interruptible wait when its poll and the work between waits are bounded. The wrapper checks stop even when every wait is immediately ready.
use futures::{Stream, StreamExt};
use task_control::{Cancelled, StopTask};
async fn run<T>(
stop: &mut StopTask<'_>,
items: &mut (impl Stream<Item = T> + Unpin),
mut process: impl FnMut(T),
) -> Result<(), Cancelled> {
loop {
let Some(item) = stop.until_stopped(items.next()).await? else {
return Ok(());
};
process(item);
}
}§Whole-loop waits
When wrapping the whole loop, obtain a StopCheck before borrowing stop
for the wait. Check it before fetching each new unit of work. The wrapper
interrupts blocked waits; the checks interrupt continuously ready work.
use futures::{Stream, StreamExt};
use task_control::{Cancelled, StopTask};
async fn run<T>(
stop: &mut StopTask<'_>,
items: &mut (impl Stream<Item = T> + Unpin),
mut process: impl FnMut(T),
) -> Result<(), Cancelled> {
let check = stop.check_handle()?;
stop.until_stopped(async {
loop {
check.check()?;
let Some(item) = items.next().await else {
return Ok(());
};
process(item);
}
})
.await?
}§Choosing check boundaries
- Check between bounded batches rather than inside every item. Queue capacity is not a bound if buffers or credits can be recycled while draining.
- Cover nested loops and each concurrent branch, not just worker entry. A shared helper can instead return after one bounded step to a checked caller.
- Keep accepted I/O and partial progress in the task or its state across awaits. Finish required queue publication and coordinator handoffs before returning cancellation; do not put a check between consuming work and recording the state needed to resume it.
Keep cancellation separate from operational failures. Do not catch and log
Cancelled and then return Ok(()), which prevents the worker from resuming.
A synchronous check does not interrupt an outstanding wait or yield the
executor; use until_stopped for waits that must be interruptible.
Structs§
- Cancelled
- The return error from
AsyncRun::runindicating the task has not yet finished executing. - Stop
Check - A control-request check that can be used while
StopTaskis borrowed by a wait. - Stop
Task - A future indicating that the task should return for event processing or because the task was stopped.
- Task
Control - A task wrapper that runs a task asynchronously and provides access to its state and control over its execution (start/stop).
Traits§
- Async
Run - A method implemented by a task that can be run and stopped, storing
transient state in
S. - Inspect
Task - A trait for inspecting a task and its associated state.
- Inspect
Task Mut - A trait for mutably inspecting a task and its associated state.