mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 13:10:19 +00:00
57 lines
1.5 KiB
Rust
57 lines
1.5 KiB
Rust
use std::{
|
|
fmt,
|
|
panic::{self, UnwindSafe},
|
|
};
|
|
|
|
/// A panic payload indicating that execution of a salsa query was cancelled.
|
|
///
|
|
/// This can occur for a few reasons:
|
|
/// *
|
|
/// *
|
|
/// *
|
|
#[derive(Debug)]
|
|
#[non_exhaustive]
|
|
pub enum Cancelled {
|
|
/// The query was operating on revision R, but there is a pending write to move to revision R+1.
|
|
#[non_exhaustive]
|
|
PendingWrite,
|
|
|
|
/// The query was blocked on another thread, and that thread panicked.
|
|
#[non_exhaustive]
|
|
PropagatedPanic,
|
|
}
|
|
|
|
impl Cancelled {
|
|
pub(crate) fn throw(self) -> ! {
|
|
// We use resume and not panic here to avoid running the panic
|
|
// hook (that is, to avoid collecting and printing backtrace).
|
|
std::panic::resume_unwind(Box::new(self));
|
|
}
|
|
|
|
/// Runs `f`, and catches any salsa cancellation.
|
|
pub fn catch<F, T>(f: F) -> Result<T, Cancelled>
|
|
where
|
|
F: FnOnce() -> T + UnwindSafe,
|
|
{
|
|
match panic::catch_unwind(f) {
|
|
Ok(t) => Ok(t),
|
|
Err(payload) => match payload.downcast() {
|
|
Ok(cancelled) => Err(*cancelled),
|
|
Err(payload) => panic::resume_unwind(payload),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for Cancelled {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let why = match self {
|
|
Cancelled::PendingWrite => "pending write",
|
|
Cancelled::PropagatedPanic => "propagated panic",
|
|
};
|
|
f.write_str("cancelled because of ")?;
|
|
f.write_str(why)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for Cancelled {}
|