unwind_context/panic_detector.rs
1/// An utility trait which is used to detect panic.
2///
3/// # Examples
4///
5/// ```rust
6/// use core::sync::atomic::{self, AtomicBool};
7///
8/// use unwind_context::unwind_context_with_fmt;
9///
10/// #[derive(Copy, Clone, Debug)]
11/// pub struct NoStdPanicFlag<'a>(&'a AtomicBool);
12///
13/// impl unwind_context::PanicDetector for NoStdPanicFlag<'_> {
14/// fn is_panicking(&self) -> bool {
15/// self.0.load(atomic::Ordering::Relaxed)
16/// }
17/// }
18///
19/// fn func(foo: u32, bar: &str, writer: &mut String, panic_flag: NoStdPanicFlag<'_>) {
20/// let ctx =
21/// unwind_context_with_fmt!((foo, bar), writer = writer, panic_detector = panic_flag,);
22/// // ...
23/// }
24/// ```
25
26pub trait PanicDetector {
27 /// Determines whether the current thread is unwinding because of panic.
28 ///
29 /// # Panics
30 ///
31 /// Implementations should generally avoid [`panic!`]ing, because
32 /// `is_panicking()` may itself be called during unwinding due to a
33 /// panic, and if the `is_panicking()` panics in that situation (a “double
34 /// panic”), this will likely abort the program.
35 fn is_panicking(&self) -> bool;
36}
37
38/// A default [`PanicDetector`] for a crates compiled with the Rust standard
39/// library.
40///
41/// It uses `std::thread::panicking()` to detect whether the current thread is
42/// unwinding because of panic.
43///
44/// # Examples
45///
46/// ```rust
47/// use unwind_context::unwind_context_with_fmt;
48///
49/// fn func(foo: u32, bar: &str, writer: &mut String) {
50/// let ctx = unwind_context_with_fmt!(
51/// (foo, bar),
52/// writer = writer,
53/// panic_detector = unwind_context::StdPanicDetector,
54/// );
55/// // ...
56/// }
57/// ```
58#[cfg(feature = "std")]
59#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
60#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
61pub struct StdPanicDetector;
62
63#[cfg(feature = "std")]
64#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
65impl PanicDetector for StdPanicDetector {
66 #[inline]
67 fn is_panicking(&self) -> bool {
68 std::thread::panicking()
69 }
70}