actix_rt::task

# Struct JoinHandle

    pub struct JoinHandle<T> { /* private fields */ }

Expand description

An owned permission to join on a task (await its termination).

This can be thought of as the equivalent of `std::thread::JoinHandle` for a Tokio task rather than a thread. Note that the background task associated with this `JoinHandle` started running immediately when you called spawn, even if you have not yet awaited the `JoinHandle`.

A `JoinHandle` detaches the associated task when it is dropped, which means that there is no longer any handle to the task, and no way to `join` on it.

This `struct` is created by the `task::spawn` and `task::spawn_blocking` functions.

## §Cancel safety

The `&mut JoinHandle<T>` type is cancel safe. If it is used as the event in a `tokio::select!` statement and some other branch completes first, then it is guaranteed that the output of the task is not lost.

If a `JoinHandle` is dropped, then the task continues running in the background and its return value is lost.

## §Examples

Creation from `task::spawn`:

    use tokio::task;

    let join_handle: task::JoinHandle<_> = task::spawn(async {
        // some work here
    });

Creation from `task::spawn_blocking`:

    use tokio::task;

    let join_handle: task::JoinHandle<_> = task::spawn_blocking(|| {
        // some blocking work here
    });

The generic parameter `T` in `JoinHandle<T>` is the return type of the spawned task. If the return value is an `i32`, the join handle has type `JoinHandle<i32>`:

    use tokio::task;

    let join_handle: task::JoinHandle<i32> = task::spawn(async {
        5 + 3
    });

If the task does not have a return value, the join handle has type `JoinHandle<()>`:

    use tokio::task;

    let join_handle: task::JoinHandle<()> = task::spawn(async {
        println!("I return nothing.");
    });

Note that `handle.await` doesn’t give you the return type directly. It is wrapped in a `Result` because panics in the spawned task are caught by Tokio. The `?` operator has to be double chained to extract the returned value:

    use tokio::task;
    use std::io;

    #[tokio::main]
    async fn main() -> io::Result<()> {
        let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
            Ok(5 + 3)
        });

        let result = join_handle.await??;
        assert_eq!(result, 8);
        Ok(())
    }

If the task panics, the error is a `JoinError` that contains the panic:

    use tokio::task;
    use std::io;
    use std::panic;

    #[tokio::main]
    async fn main() -> io::Result<()> {
        let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async {
            panic!("boom");
        });

        let err = join_handle.await.unwrap_err();
        assert!(err.is_panic());
        Ok(())
    }

Child being detached and outliving its parent:

    use tokio::task;
    use tokio::time;
    use std::time::Duration;

    let original_task = task::spawn(async {
        let _detached_task = task::spawn(async {
            // Here we sleep to make sure that the first task returns before.
            time::sleep(Duration::from_millis(10)).await;
            // This will be called, even though the JoinHandle is dropped.
            println!("♫ Still alive ♫");
        });
    });

    original_task.await.expect("The task being joined has panicked");
    println!("Original task is joined.");

    // We make sure that the new task has time to run, before the main
    // task returns.

    time::sleep(Duration::from_millis(1000)).await;

## Implementations§

§

### impl<T> JoinHandle<T>

#### pub fn abort(&self)

Abort the task associated with the handle.

Awaiting a cancelled task might complete as usual if the task was already completed at the time it was cancelled, but most likely it will fail with a cancelled `JoinError`.

Be aware that tasks spawned using `spawn_blocking` cannot be aborted because they are not async. If you call `abort` on a `spawn_blocking` task, then this will not have any effect, and the task will continue running normally. The exception is if the task has not started running yet; in that case, calling `abort` may prevent the task from starting.

See also the module level docs for more information on cancellation.

    use tokio::time;

    let mut handles = Vec::new();

    handles.push(tokio::spawn(async {
       time::sleep(time::Duration::from_secs(10)).await;
       true
    }));

    handles.push(tokio::spawn(async {
       time::sleep(time::Duration::from_secs(10)).await;
       false
    }));

    for handle in &handles {
        handle.abort();
    }

    for handle in handles {
        assert!(handle.await.unwrap_err().is_cancelled());
    }

#### pub fn is_finished(&self) -> bool

Checks if the task associated with this `JoinHandle` has finished.

Please note that this method can return `false` even if `abort` has been called on the task. This is because the cancellation process may take some time, and this method does not return `true` until it has completed.

    use tokio::time;

    let handle1 = tokio::spawn(async {
        // do some stuff here
    });
    let handle2 = tokio::spawn(async {
        // do some other stuff here
        time::sleep(time::Duration::from_secs(10)).await;
    });
    // Wait for the task to finish
    handle2.abort();
    time::sleep(time::Duration::from_secs(1)).await;
    assert!(handle1.is_finished());
    assert!(handle2.is_finished());

#### pub fn abort_handle(&self) -> AbortHandle

Returns a new `AbortHandle` that can be used to remotely abort this task.

Awaiting a task cancelled by the `AbortHandle` might complete as usual if the task was already completed at the time it was cancelled, but most likely it will fail with a cancelled `JoinError`.

    use tokio::{time, task};

    let mut handles = Vec::new();

    handles.push(tokio::spawn(async {
       time::sleep(time::Duration::from_secs(10)).await;
       true
    }));

    handles.push(tokio::spawn(async {
       time::sleep(time::Duration::from_secs(10)).await;
       false
    }));

    let abort_handles: Vec<task::AbortHandle> = handles.iter().map(|h| h.abort_handle()).collect();

    for handle in abort_handles {
        handle.abort();
    }

    for handle in handles {
        assert!(handle.await.unwrap_err().is_cancelled());
    }

## Trait Implementations§

§

### impl<T> Debug for JoinHandle<T>
where T: Debug,

§

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

Formats the value using the given formatter. Read more
§

### impl<T> Drop for JoinHandle<T>

§

#### fn drop(&mut self)

Executes the destructor for this type. Read more
§

### impl<T> Future for JoinHandle<T>

§

#### type Output = Result<T, JoinError>

The type of value produced on completion.
§

#### fn poll( self: Pin<&mut JoinHandle<T>>, cx: &mut Context<'_>, ) -> Poll<<JoinHandle<T> as Future>::Output>

Attempts to resolve the future to a final value, registering the current task for wakeup if the value is not yet available. Read more
§

### impl<T> RefUnwindSafe for JoinHandle<T>

§

### impl<T> Send for JoinHandle<T>
where T: Send,

§

### impl<T> Sync for JoinHandle<T>
where T: Send,

§

### impl<T> Unpin for JoinHandle<T>

§

### impl<T> UnwindSafe for JoinHandle<T>

## Auto Trait Implementations§

§

### impl<T> Freeze for JoinHandle<T>

## 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.

§

### impl<T> FutureExt for T
where T: Future + ?Sized,

§

#### fn map<U, F>(self, f: F) -> Map<Self, F>
where F: FnOnce(Self::Output) -> U, Self: Sized,

Map this future’s output to a different type, returning a new future of the resulting type. Read more
§

#### fn map_into<U>(self) -> MapInto<Self, U>
where Self::Output: Into<U>, Self: Sized,

Map this future’s output to a different type, returning a new future of the resulting type. Read more
§

#### fn then<Fut, F>(self, f: F) -> Then<Self, Fut, F>
where F: FnOnce(Self::Output) -> Fut, Fut: Future, Self: Sized,

Chain on a computation for when a future finished, passing the result of the future to the provided closure `f`. Read more
§

#### fn left_future<B>(self) -> Either<Self, B>
where B: Future<Output = Self::Output>, Self: Sized,

Wrap this future in an `Either` future, making it the left-hand variant of that `Either`. Read more
§

#### fn right_future<A>(self) -> Either<A, Self>
where A: Future<Output = Self::Output>, Self: Sized,

Wrap this future in an `Either` future, making it the right-hand variant of that `Either`. Read more
§

#### fn into_stream(self) -> IntoStream<Self>
where Self: Sized,

Convert this future into a single element stream. Read more
§

#### fn flatten(self) -> Flatten<Self>
where Self::Output: Future, Self: Sized,

Flatten the execution of this future when the output of this future is itself another future. Read more
§

#### fn flatten_stream(self) -> FlattenStream<Self>
where Self::Output: Stream, Self: Sized,

Flatten the execution of this future when the successful result of this future is a stream. Read more
§

#### fn fuse(self) -> Fuse<Self>
where Self: Sized,

Fuse a future such that `poll` will never again be called once it has completed. This method can be used to turn any `Future` into a `FusedFuture`. Read more
§

#### fn inspect<F>(self, f: F) -> Inspect<Self, F>
where F: FnOnce(&Self::Output), Self: Sized,

Do something with the output of a future before passing it on. Read more
§

#### fn catch_unwind(self) -> CatchUnwind<Self>
where Self: Sized + UnwindSafe,

Catches unwinding panics while polling the future. Read more
§

#### fn shared(self) -> Shared<Self>
where Self: Sized, Self::Output: Clone,

Create a cloneable handle to this future where all handles will resolve to the same result. Read more
§

#### fn boxed<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>
where Self: Sized + Send + 'a,

Wrap the future in a Box, pinning it. Read more
§

#### fn boxed_local<'a>(self) -> Pin<Box<dyn Future<Output = Self::Output> + 'a>>
where Self: Sized + 'a,

Wrap the future in a Box, pinning it. Read more
§

#### fn unit_error(self) -> UnitError<Self>
where Self: Sized,

Turns a `Future<Output = T>` into a `TryFuture<Ok = T, Error = ()`>.
§

#### fn never_error(self) -> NeverError<Self>
where Self: Sized,

Turns a `Future<Output = T>` into a `TryFuture<Ok = T, Error = Never`>.
§

#### fn poll_unpin(&mut self, cx: &mut Context<'_>) -> Poll<Self::Output>
where Self: Unpin,

A convenience for calling `Future::poll` on `Unpin` future types.
§

#### fn now_or_never(self) -> Option<Self::Output>
where Self: Sized,

Evaluates and consumes the future, returning the resulting output if the future is ready after the first call to `Future::poll`. Read more
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<F> IntoFuture for F
where F: Future,

source §

#### type Output = <F as Future>::Output

The output that the future will produce on completion.
source §

#### type IntoFuture = F

Which kind of future are we turning this into?
source §

#### fn into_future(self) -> <F as IntoFuture>::IntoFuture

Creates a future from a value. Read more
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.
§

### impl<F, T, E> TryFuture for F
where F: Future<Output = Result<T, E>> + ?Sized,

§

#### type Ok = T

The type of successful values yielded by this future
§

#### type Error = E

The type of failures yielded by this future
§

#### fn try_poll( self: Pin<&mut F>, cx: &mut Context<'_>, ) -> Poll<<F as Future>::Output>

Poll this `TryFuture` as if it were a `Future`. Read more
§

### impl<Fut> TryFutureExt for Fut
where Fut: TryFuture + ?Sized,

§

#### fn map_ok<T, F>(self, f: F) -> MapOk<Self, F>
where F: FnOnce(Self::Ok) -> T, Self: Sized,

Maps this future’s success value to a different value. Read more
§

#### fn map_ok_or_else<T, E, F>(self, e: E, f: F) -> MapOkOrElse<Self, F, E>
where F: FnOnce(Self::Ok) -> T, E: FnOnce(Self::Error) -> T, Self: Sized,

Maps this future’s success value to a different value, and permits for error handling resulting in the same type. Read more
§

#### fn map_err<E, F>(self, f: F) -> MapErr<Self, F>
where F: FnOnce(Self::Error) -> E, Self: Sized,

Maps this future’s error value to a different value. Read more
§

#### fn err_into<E>(self) -> ErrInto<Self, E>
where Self: Sized, Self::Error: Into<E>,

Maps this future’s `Error` to a new error type using the `Into` trait. Read more
§

#### fn ok_into<U>(self) -> OkInto<Self, U>
where Self: Sized, Self::Ok: Into<U>,

Maps this future’s `Ok` to a new type using the `Into` trait.
§

#### fn and_then<Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
where F: FnOnce(Self::Ok) -> Fut, Fut: TryFuture<Error = Self::Error>, Self: Sized,

Executes another future after this one resolves successfully. The success value is passed to a closure to create this subsequent future. Read more
§

#### fn or_else<Fut, F>(self, f: F) -> OrElse<Self, Fut, F>
where F: FnOnce(Self::Error) -> Fut, Fut: TryFuture<Ok = Self::Ok>, Self: Sized,

Executes another future if this one resolves to an error. The error value is passed to a closure to create this subsequent future. Read more
§

#### fn inspect_ok<F>(self, f: F) -> InspectOk<Self, F>
where F: FnOnce(&Self::Ok), Self: Sized,

Do something with the success value of a future before passing it on. Read more
§

#### fn inspect_err<F>(self, f: F) -> InspectErr<Self, F>
where F: FnOnce(&Self::Error), Self: Sized,

Do something with the error value of a future before passing it on. Read more
§

#### fn try_flatten(self) -> TryFlatten<Self, Self::Ok>
where Self::Ok: TryFuture<Error = Self::Error>, Self: Sized,

Flatten the execution of this future when the successful result of this future is another future. Read more
§

#### fn try_flatten_stream(self) -> TryFlattenStream<Self>
where Self::Ok: TryStream<Error = Self::Error>, Self: Sized,

Flatten the execution of this future when the successful result of this future is a stream. Read more
§

#### fn unwrap_or_else<F>(self, f: F) -> UnwrapOrElse<Self, F>
where Self: Sized, F: FnOnce(Self::Error) -> Self::Ok,

Unwraps this future’s output, producing a future with this future’s `Ok` type as its `Output` type. Read more
§

#### fn into_future(self) -> IntoFuture<Self>
where Self: Sized,

Wraps a [`TryFuture`] into a type that implements `Future`. Read more
§

#### fn try_poll_unpin( &mut self, cx: &mut Context<'_>, ) -> Poll<Result<Self::Ok, Self::Error>>
where Self: Unpin,

A convenience method for calling [`TryFuture::try_poll`] on `Unpin` future types.
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.