pub struct Task<F> { /* private fields */ }Expand description
A scheduled asynchronous task that manages execution, dependencies, error handling, and lifecycle state.
The task consists of an execution unit that holds the main future. It also manages dependencies, including direct and detached ones, and determines how they are polled. All dependencies (if any) must complete before this task executes. Direct dependencies may be polled:
- Concurrently (cooperatively interleaved)
- Synchronously (one-by-one in sequence)
- Detached (spawned in parallel threads)
Cloures can be also added as detached dependencies in separate queue which executes them in parallel. Error handling behavior can be defined to control whether dependencies should stop execution based on the returned value.
Implementations§
Source§impl<F> Task<F>where
F: Future,
impl<F> Task<F>where
F: Future,
Sourcepub fn new(future: F) -> Self
pub fn new(future: F) -> Self
Creates a new task with the given future.
The provided future represents the main task to be executed. Dependencies can be added
using depends_on or depends_on_if, and they will be polled according to the specified
polling strategy.
If the future F returns a value, that value must implement
the Default trait, as it will be used as the default value for the task if it is
canceled.
The task itself does not start running immediately; it must be .awaited or run with Scheduler to execute.
Sourcepub fn depends_on<R>(
&mut self,
future: impl Future<Output = R> + Send + Sync + 'static,
) -> &mut Self
pub fn depends_on<R>( &mut self, future: impl Future<Output = R> + Send + Sync + 'static, ) -> &mut Self
Adds a dependency that must complete before this task continues execution.
The provided future is added as a dependency and will be polled according to the task’s polling strategy. Dependencies can be polled sequentially, concurrently, or in a detached manner (executed on a separate thread from a thread pool).
By default, dependencies are polled concurrently.
- If the polling strategy is sequential or concurrent, the dependency will be polled in the same executor context.
- If the polling strategy is detached, the dependency will be polled in a separate thread pool, so it must avoid using executor-specific functions, like
tokio::time::sleep(). In this case dependencies should only use general-purpose futures that are agnostic to any particular runtime or executor.
This method ensures that the given future will be polled as part of the dependency execution flow but does not affect whether subsequent dependencies or the main task should execute.
Sourcepub fn depends_on_if<R>(
&mut self,
future: impl Future<Output = R> + Send + Sync + 'static,
should_continue: impl FnOnce(R) -> bool + Send + Sync + 'static,
) -> &mut Self
pub fn depends_on_if<R>( &mut self, future: impl Future<Output = R> + Send + Sync + 'static, should_continue: impl FnOnce(R) -> bool + Send + Sync + 'static, ) -> &mut Self
Adds a conditional dependency that may prevent the main task from running and cancel certain dependencies.
This method behaves the same as depends_on but with the added feature that execution is conditional based on the result of the given future.
The provided future is added as a dependency and will be polled according to the
task’s polling strategy (sequential, concurrent, or detached). Once the future completes,
its result is passed to the should_continue closure.
- If
should_continuereturnstrue, execution of other dependencies continues as usual, and the main task will run. - If
should_continuereturnsfalse, the main task will not run, and it will instead return its default value. - Other dependencies may or may not start execution, depending on the polling strategy:
- If the polling strategy is sequential, no further dependencies will run.
- If the polling strategy is concurrent or detached, some dependencies may start execution before cancellation occurs.
- Any dependencies that have already started will be canceled. Dependencies that have not started will not run.
This method is useful for conditionally stopping execution based on the result of a dependency.
§Example
task
// If `dependency_2` fails will be canceled if still running.
.depends_on(dependency_1)
.depends_on_if(dependency_2, |result| result > 0)
// If `dependency_2` fails, will be canceled if running or not run at all.
.depends_on(dependency_3);
task.await; // If `dependency_2` fails, the main task will not run.Sourcepub fn depends_on_detached<R>(
&mut self,
task_fn: impl FnOnce() -> R + Send + Sync + 'static,
) -> &mut Self
pub fn depends_on_detached<R>( &mut self, task_fn: impl FnOnce() -> R + Send + Sync + 'static, ) -> &mut Self
Adds a dependency that runs in a separate thread from the thread pool.
Unlike depends_on, which polls futures asynchronously, this method takes a synchronous closure (FnOnce)
and executes it in a dedicated thread from the thread pool.
This is useful for integrating CPU-bound or blocking operations that should not be executed within an async context. Each provided closure runs fully in its own thread, independent of the task’s main execution flow.
Threads for these dependencies are managed by a thread pool, ensuring efficient resource utilization.
The main task will not execute until all detached closures have completed.
§Example
task.depends_on_detached(|| {
// Perform some blocking computation.
std::thread::sleep(std::time::Duration::from_secs(1));
});
task.await; // Main task runs only after all detached closures finish.Sourcepub fn depends_on_detached_if<R: 'static>(
&mut self,
task_fn: impl FnOnce() -> R + Send + Sync + 'static,
should_continue: impl FnOnce(R) -> bool + Send + Sync + 'static,
) -> &mut Self
pub fn depends_on_detached_if<R: 'static>( &mut self, task_fn: impl FnOnce() -> R + Send + Sync + 'static, should_continue: impl FnOnce(R) -> bool + Send + Sync + 'static, ) -> &mut Self
Adds a dependency that runs in a separate thread from the thread pool, with a condition to determine task continuation.
Similar to depends_on_detached, this method executes a synchronous closure (FnOnce) in a dedicated thread
from the thread pool. However, it also takes a should_continue closure, which receives the result of the
dependency and determines whether execution should proceed.
If should_continue returns false, any already-running detached dependencies will be canceled,
and dependencies that have not yet started will not run. The main task will not execute.
Threads for these dependencies are managed by a thread pool, ensuring efficient resource utilization.
Note: This is separate from the detached polling strategy used for async dependencies.
§Example
task
.depends_on_detached_if(
|| {
// Perform some blocking computation.
42
},
// If `result <= 0`, running dependencies will be canceled, pending ones
// won't start, and the main task won't run.
|result| result > 0,
)
.depends_on_detached(|| println!("Another detached task"));
task.await; // Main task runs only if `should_continue` returned true.Sourcepub fn get_handle(&self) -> TaskHandle
pub fn get_handle(&self) -> TaskHandle
Returns a handle for canceling the task and its dependencies.
The returned TaskHandle can be used to prevent the task from starting or to stop it if already running.
Any pending dependencies will not start, while running dependencies will be stopped.
Sourcepub fn sequential(&mut self) -> &mut Self
pub fn sequential(&mut self) -> &mut Self
Sets the polling strategy to sequential.
Dependencies will be polled one at a time in the order they were added,
ensuring that each dependency completes before the next one starts.
Sourcepub fn detached(&mut self) -> &mut Self
pub fn detached(&mut self) -> &mut Self
Sets the polling strategy to detached.
Dependencies will be polled in separate threads from the thread pool,
allowing them to run independently. This means dependencies will execute in
parallel without blocking the main task.
Note: When using this strategy, dependencies must not use executor-specific
code (e.g., tokio::time::sleep()), as this will cause a panic.
Sourcepub fn concurrent(&mut self) -> &mut Self
pub fn concurrent(&mut self) -> &mut Self
Sets the polling strategy to concurrent.
Dependencies will be polled simultaneously, allowing them to make progress
independently. This strategy maximizes concurrency and is the default if
no other strategy is set.
Trait Implementations§
Auto Trait Implementations§
impl<F> !RefUnwindSafe for Task<F>
impl<F> !UnwindSafe for Task<F>
impl<F> Freeze for Task<F>
impl<F> Send for Task<F>
impl<F> Sync for Task<F>
impl<F> Unpin for Task<F>
impl<F> UnsafeUnpin for Task<F>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn map<U, F>(self, f: F) -> Map<Self, F> ⓘ
fn map<U, F>(self, f: F) -> Map<Self, F> ⓘ
Source§fn map_into<U>(self) -> MapInto<Self, U> ⓘ
fn map_into<U>(self) -> MapInto<Self, U> ⓘ
Source§fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F> ⓘ
fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F> ⓘ
f. Read moreSource§fn left_future<B>(self) -> Either<Self, B> ⓘ
fn left_future<B>(self) -> Either<Self, B> ⓘ
Source§fn right_future<A>(self) -> Either<A, Self> ⓘ
fn right_future<A>(self) -> Either<A, Self> ⓘ
Source§fn into_stream(self) -> IntoStream<Self>where
Self: Sized,
fn into_stream(self) -> IntoStream<Self>where
Self: Sized,
Source§fn flatten(self) -> Flatten<Self> ⓘ
fn flatten(self) -> Flatten<Self> ⓘ
Source§fn flatten_stream(self) -> FlattenStream<Self>
fn flatten_stream(self) -> FlattenStream<Self>
Source§fn fuse(self) -> Fuse<Self> ⓘwhere
Self: Sized,
fn fuse(self) -> Fuse<Self> ⓘwhere
Self: Sized,
poll will never again be called once it has
completed. This method can be used to turn any Future into a
FusedFuture. Read moreSource§fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ
fn inspect<F>(self, f: F) -> Inspect<Self, F> ⓘ
Source§fn catch_unwind(self) -> CatchUnwind<Self> ⓘwhere
Self: Sized + UnwindSafe,
fn catch_unwind(self) -> CatchUnwind<Self> ⓘwhere
Self: Sized + UnwindSafe,
Source§fn remote_handle(self) -> (Remote<Self>, RemoteHandle<Self::Output>)where
Self: Sized,
fn remote_handle(self) -> (Remote<Self>, RemoteHandle<Self::Output>)where
Self: Sized,
() on completion and sends
its output to another future on a separate task. Read moreSource§fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
Source§fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>where
Self: Sized + 'a,
fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>where
Self: Sized + 'a,
Source§fn unit_error(self) -> UnitError<Self> ⓘwhere
Self: Sized,
fn unit_error(self) -> UnitError<Self> ⓘwhere
Self: Sized,
Future<Output = T> into a
TryFuture<Ok = T, Error = ()>.Source§fn never_error(self) -> NeverError<Self> ⓘwhere
Self: Sized,
fn never_error(self) -> NeverError<Self> ⓘwhere
Self: Sized,
Future<Output = T> into a
TryFuture<Ok = T, Error = Never>.