1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#[derive(Debug)]
pub struct SimpleTerminate<PPEL: ParsedPanicErrorLogger>
{
lock: AtomicU64,
error_logger: PPEL,
}
impl<PPEL: ParsedPanicErrorLogger> Terminate for SimpleTerminate<PPEL>
{
#[inline(always)]
fn begin_termination(&self)
{
self.compare_and_swap(Self::NormalTerminate)
}
#[inline(always)]
fn begin_termination_due_to_irrecoverable_error(&self, panic_payload: &(dyn Any + Send), location: Option<&Location>)
{
self.compare_and_swap(Self::PanicTerminate);
let parsed_panic = ParsedPanic::parse(panic_payload, location);
self.error_logger.log(parsed_panic)
}
#[inline(always)]
fn should_finish(&self) -> bool
{
self.load() != Self::Continue
}
#[inline(always)]
fn terminated_due_to_panic_or_irrecoverable_error(&self) -> bool
{
let value = self.load();
debug_assert_ne!(value, Self::Continue, "should not be checking this unless `should_finish()` was `true`");
value == Self::PanicTerminate
}
}
impl<PPEL: ParsedPanicErrorLogger> SimpleTerminate<PPEL>
{
const Continue: u64 = 0x00;
const NormalTerminate: u64 = 0x01;
const PanicTerminate: u64 = 0x02;
#[inline(always)]
pub fn new(error_logger: PPEL) -> Arc<Self>
{
Arc::new
(
Self
{
lock: AtomicU64::new(Self::Continue),
error_logger,
}
)
}
#[inline(always)]
fn compare_and_swap(&self, termination_reason: u64)
{
let _ = self.lock.compare_exchange(Self::Continue, termination_reason, AcqRel, Acquire);
}
#[inline(always)]
fn load(&self) -> u64
{
self.lock.load(Acquire)
}
}