tracing_mutex/
reporting.rs1use std::backtrace::Backtrace;
6use std::borrow::Cow;
7use std::fmt::Write;
8use std::sync::Arc;
9use std::sync::atomic::{AtomicBool, Ordering};
10
11#[cfg(feature = "backtraces")]
12pub type Dep = MutexDep<Arc<Backtrace>>;
13#[cfg(not(feature = "backtraces"))]
14pub type Dep = MutexDep<()>;
15
16const BASE_MESSAGE: &str = "Found cycle in mutex dependency graph:";
18
19static SHOULD_PANIC: AtomicBool = AtomicBool::new(true);
20
21pub fn suppress_panics() {
27 SHOULD_PANIC.store(false, Ordering::Relaxed);
28}
29
30pub(crate) fn report_cycle(cycle: &[Dep]) {
31 let message = Dep::message(cycle);
32 if SHOULD_PANIC.load(Ordering::Relaxed) {
33 panic!("{message}");
34 } else {
35 eprintln!("{message}");
36 }
37}
38
39pub trait Reportable: Clone {
40 fn capture() -> Self;
42
43 fn message(trace: &[Self]) -> Cow<'static, str>;
45}
46
47#[derive(Clone)]
48pub struct MutexDep<T>(T);
49
50impl Reportable for MutexDep<()> {
55 fn capture() -> Self {
56 Self(())
57 }
58
59 fn message(_trace: &[Self]) -> Cow<'static, str> {
60 Cow::Borrowed(BASE_MESSAGE)
61 }
62}
63
64impl Reportable for MutexDep<Arc<Backtrace>> {
72 fn capture() -> Self {
73 Self(Arc::new(Backtrace::capture()))
74 }
75
76 fn message(trace: &[Self]) -> Cow<'static, str> {
77 let mut message = format!("{BASE_MESSAGE}\n");
78
79 for entry in trace {
80 let _ = writeln!(message, "{}", entry.0);
81 }
82
83 message.into()
84 }
85}