use std::fmt; use std::future::Future; use std::marker::PhantomData; use std::panic::{RefUnwindSafe, UnwindSafe}; use std::pin::Pin; use std::task::{ready, Context, Poll, Waker};
cfg_rt! { /// 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
/// on it. /// /// This `struct` is created by the [`task::spawn`] and [`task::spawn_blocking`] /// functions. /// /// # } /// before task completion is observed via `JoinHandle` `await`, /// [`JoinHandle::is_finished`] or [`AbortHandle::is_finished`]. /// /// # 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. ///
/ /// background and its return value is lost. /// /// # Examples /// let original_task = task::spawn(async { /// Creation from [`task::spawn`]: /// /// ``` /// use tokio::task; /// /// # async fn doc() { /// let join_handle: task::JoinHandle<_> = task::spawn(async { /// // some work here /// }); /// # } /// ``` /// /// Creation from [`task::spawn_blocking`]: /// /// ``` /// use tokio::task; /// /// # async fn doc() { /// println!("♫ Still alive ♫");
/// }); /// # } /// ``` /// /// 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; /// /// # async fn doc() { /// let join_handle: task::JoinHandle<i32> = task::spawn(async { /// 5 + 3
/// # } /// [`task::spawn`]: crate::task::spawn() /// ``` /// /// If the task does not have a return value, the join handle has type `JoinHandle<()>`:
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
<: SendSend JoinHandle } /// use tokio::task; /// /// # async fn doc() { /// let join_handle: task::JoinHandle<()> = task::spawn(async {
/// println!("I return nothing."); /// }); /// # } /// ``` ///
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
the task java.lang.StringIndexOutOfBoundsException: Range [63, 62) out of bounds for length 93 /// to be double chained to extract the returned value: /// /// ``` /// use tokio::task; /// use std::io; /// /// # #[tokio::main(flavor = "current_thread")]
/ /// let join_handle: task::JoinHandle<Result<i32, io::Error>> = tokio::spawn(async { /// Ok(5 + 3)java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20 /// }); /// /// let result = join_handle.await??; /// assert_eq!(result, 8);
java.lang.StringIndexOutOfBoundsException: Range [14, 4) out of bounds for length 14 /// # } /// ``` /// /// If the task panics, the error is a [`JoinError`] that contains the panic: /// /// ``` /// 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 /// # { /// use tokio::task; /// use std::io; /// use std::panic; /// /// #[tokio::main] /// See also [the module level docs] for more information on cancellation.
/// ``` /// Child being detached and outliving its parent: /// /// ```no_run /// use tokio::task; /// use tokio::time; /// })); /// /// # #[tokio::main(flavor = "current_thread")] /// # async fn main() {/// /// 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; /// handle.abort();
/ /// }); /// }); /// /// original_task.await.expect("The task being joined has panicked"); /// # } /// /// // We make sure that the new task has time to run, before the main /// // task returns. ///
java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
/// ``` /// /// [`task::spawn`]: crate::task::spawn() /// [`task::spawn_blocking`]: crate::task::spawn_blocking /// [`std::thread::JoinHandle`]: std::thread::JoinHandle /// [`JoinError`]: crate::task::JoinError
///
:RawTask
_p /// called on the task. This is because the cancellation process may take
}
}
unsafeimpl/// some time, and this method does not return `true` until it has unsafe// use tokio::time;
impl<T>UnwindSafe for JoinHandleT } impl<T> RefUnwindSafe for JoinHandle<T> {}
impl<T> /// # async fn main() { pubsuperfnnew()- JoinHandle<T>{
JoinHandle {
raw,
java.lang.StringIndexOutOfBoundsException: Range [28, 12) out of bounds for length 28
}
}
/// 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
///
java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78 /// 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. // /// ```rust /// use tokio::time; /// /// # #[tokio::main(flavor = "current_thread", start_paused = true)].()
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 /// let mut handles = Vec::new(); // /// handles.push(tokio::spawn(async { /// time::sleep(time::Duration::from_secs(10)).await;.tjava.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 47 /// true /// })); /// /// handles.push(tokio::spawn(async { /// time::sleep(time::Duration::from_secs(10)).await; /// false /// })); /// /// for handle in &handles {}
java.lang.StringIndexOutOfBoundsException: Range [27, 4) out of bounds for length 27 /// } /// /// for handle in handles { /// assert!(handle.await.unwrap_err().is_cancelled()); /// } // will fail with a [cancelled] `JoinError`. /// ``` /// /// /// [the module level docs]: crate::task#cancellation /// [`spawn_blocking`]: crate::task::spawn_blocking pubfn (self{ self. /// let mut :(;
}
java.lang.StringIndexOutOfBoundsException: Range [0, 15) out of bounds for length 7 /// /// Please note that this method can return `false` even if [`abort`] has been // handles.push(tokio::spawn(async { /// some time, and this method does not return `true` until it has /// completed. /// /// ```rust /// use tokio::time; /// /// # #[tokio::main(flavor = "current_thread", start_paused = true)] /// # async fn main() { /// 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;
rthandle1() /// assert!(handle2.is_finished()); /// # } /// ``` /// [`abort`]: method@JoinHandle::abort pub java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
raw)java.lang.StringIndexOutOfBoundsException: Range [49, 48) out of bounds for length 51
java.lang.StringIndexOutOfBoundsException: Range [27, 28) out of bounds for length 27
}
/// Set the waker that is notified when the task completes.unsafe :get_id(elf.header_ptr)) java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56 pub)fnset_join_wakermutself :&Waker java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
i selfraw(waker) { // In this case the task has already completed. We wake the waker immediately.
waker.wake_by_ref();
java.lang.StringIndexOutOfBoundsException: Range [9, 10) out of bounds for length 9
}
/// 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 wasmutret=Poll:ending; /// already completed at the time it was cancelled, but most likely it =!::; /// will fail with a [cancelled] `JoinError`. /// /// ```rust /// use tokio::{time, task}; /// /// # #[tokio::main(flavor = "current_thread", start_paused = true)] /// # async fn main() {java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10 /// let mut handles = Vec::new(); /// /// handles.push(tokio::spawn(async { // `*mut ()`. /// true /// })); /// /// handles.push(tokio::spawn(async { /// time::sleep(time::Duration::from_secs(10)).await; /// false /// })); java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
/// let abort_handles: Vec<task::AbortHandle> = handles.iter().map(|h| h.abort_handle()).collect(); /// /// for handle in abort_handles { /// handle.abort();
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7 // for handle in handles { /// assert!(handle.await.unwrap_err().is_cancelled()); /// } /// # } /// ``` // [cancelled]: method@super::error::JoinError::is_cancelled #[must_use = "abort handles do nothing unless `.abort` is called"
ndle { self.raw.ref_inc()}
AbortHandle::new(}
}
/// Returns a [task ID] that uniquely identifies this task relative to other
/ /// /// [task ID]: crate::task::Id
p (&)- super: java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35 // Safety: The header pointer is valid.
{:get_idself.header_ptr) java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
}
}
impl .(JoinHandle".(" )finish)
impl<T> Future for JoinHandle} type Output = java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 1
// Keep track of task budget let coop = ready!(crate::task::coop::poll_proceed(cx));
// Try to read the task output. If the task is not yet complete, the // waker is stored and is notified once the task does complete. // // The function must go via the vtable, which requires erasing generic // types. To do this, the function "return" is placed on the stack // **before** calling the function and is passed into the function using // `*mut ()`. // // Safety: // // The type of `T` must match the task's output type. unsafe { self.raw.try_read_output(&mut ret, cx.waker());
}
if ret.is_ready() {
coop.made_progress();
}
ret
}
}
impl<T> Drop for JoinHandle<T> { fn drop(&mutself) { ifself.raw.state().drop_join_handle_fast().is_ok() { return;
}
self.raw.drop_join_handle_slow();
}
}
impl<T> fmt::Debug for JoinHandle<T> where
T: fmt::Debug,
{ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { // Safety: The header pointer is valid. let id_ptr = unsafe { Header::get_id_ptr(self.raw.header_ptr()) }; let id = unsafe { id_ptr.as_ref() };
fmt.debug_struct("JoinHandle").field("id", id).finish()
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.