task: add methods for inspecting JoinErrors (#2051)

Adds `is_cancelled()` and `is_panic()` methods to `JoinError`, as well as
`into_panic()` and `try_into_panic()` methods which, when applicable, returns
the payload of the panic.
This commit is contained in:
Daniel Fox Franke
2020-01-24 11:23:58 -08:00
committed by Carl Lerche
parent 6fbaac91e0
commit 968c143acd
+89
View File
@@ -39,6 +39,95 @@ impl JoinError {
repr: Repr::Panic(Mutex::new(err)),
}
}
/// Returns true if the error was caused by the task being cancelled
pub fn is_cancelled(&self) -> bool {
match &self.repr {
Repr::Cancelled => true,
_ => false,
}
}
/// Returns true if the error was caused by the task panicking
///
/// # Examples
///
/// ```
/// use std::panic;
///
/// #[tokio::main]
/// async fn main() {
/// let err = tokio::spawn(async {
/// panic!("boom");
/// }).await.unwrap_err();
///
/// assert!(err.is_panic());
/// }
/// ```
pub fn is_panic(&self) -> bool {
match &self.repr {
Repr::Panic(_) => true,
_ => false,
}
}
/// Consumes the join error, returning the object with which the task panicked.
///
/// # Panics
///
/// `into_panic()` panics if the `Error` does not represent the underlying
/// task terminating with a panic. Use `is_panic` to check the error reason
/// or `try_into_panic` for a variant that does not panic.
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// #[tokio::main]
/// async fn main() {
/// let err = tokio::spawn(async {
/// panic!("boom");
/// }).await.unwrap_err();
///
/// if err.is_panic() {
/// // Resume the panic on the main task
/// panic::resume_unwind(err.into_panic());
/// }
/// }
/// ```
pub fn into_panic(self) -> Box<dyn Any + Send + 'static> {
self.try_into_panic()
.expect("`JoinError` reason is not a panic.")
}
/// Consumes the join error, returning the object with which the task
/// panicked if the task terminated due to a panic. Otherwise, `self` is
/// returned.
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// #[tokio::main]
/// async fn main() {
/// let err = tokio::spawn(async {
/// panic!("boom");
/// }).await.unwrap_err();
///
/// if let Ok(reason) = err.try_into_panic() {
/// // Resume the panic on the main task
/// panic::resume_unwind(reason);
/// }
/// }
/// ```
pub fn try_into_panic(self) -> Result<Box<dyn Any + Send + 'static>, JoinError> {
match self.repr {
Repr::Panic(p) => Ok(p.into_inner().expect("Extracting panic from mutex")),
_ => Err(self),
}
}
}
impl fmt::Display for JoinError {