1#![forbid(unsafe_code)]
7
8use crate::local_only::LocalOnly;
9use mesh::MeshPayload;
10use std::fmt::Debug;
11use std::sync::Arc;
12
13#[derive(Clone, Debug, MeshPayload)]
23pub struct Interrupt {
24 inner: InterruptInner,
25}
26
27impl Default for Interrupt {
28 fn default() -> Self {
29 Self::null()
30 }
31}
32
33impl Interrupt {
34 pub fn null() -> Self {
39 Self::from_event(pal_event::Event::new())
41 }
42
43 pub fn null_event() -> Self {
48 Self::from_event(pal_event::Event::new())
49 }
50
51 pub fn from_event(event: pal_event::Event) -> Self {
55 Self {
56 inner: InterruptInner::Event(Arc::new(event)),
57 }
58 }
59
60 pub fn from_cell(cell: mesh::Cell<pal_event::Event>) -> Self {
65 Self {
66 inner: InterruptInner::Cell(Arc::new(cell)),
67 }
68 }
69
70 pub fn from_fn<F>(f: F) -> Self
75 where
76 F: 'static + Send + Sync + Fn(),
77 {
78 Self {
79 inner: InterruptInner::Fn(LocalOnly(Arc::new(f))),
80 }
81 }
82
83 pub fn deliver(&self) {
85 match &self.inner {
86 InterruptInner::Event(event) => event.signal(),
87 InterruptInner::Cell(cell) => cell.with(|event| event.signal()),
88 InterruptInner::Fn(LocalOnly(f)) => f(),
89 }
90 }
91
92 pub fn event(&self) -> Option<&pal_event::Event> {
94 match &self.inner {
95 InterruptInner::Event(event) => Some(event.as_ref()),
96 _ => None,
97 }
98 }
99}
100
101#[derive(Clone, MeshPayload)]
102enum InterruptInner {
103 Event(Arc<pal_event::Event>),
104 Cell(Arc<mesh::Cell<pal_event::Event>>),
105 Fn(LocalOnly<Arc<dyn Send + Sync + Fn()>>),
106}
107
108impl Debug for InterruptInner {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 match self {
111 InterruptInner::Event(_) => f.pad("Event"),
112 InterruptInner::Cell(_) => f.pad("Cell"),
113 InterruptInner::Fn(_) => f.pad("Fn"),
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::Interrupt;
121 use pal_async::async_test;
122
123 #[test]
124 fn test_interrupt_event() {
125 let event = pal_event::Event::new();
126 let interrupt = Interrupt::from_event(event.clone());
127 interrupt.deliver();
128 assert!(event.try_wait());
129 }
130
131 #[async_test]
132 async fn test_interrupt_cell() {
133 let mut event = pal_event::Event::new();
134 let (mut updater, cell) = mesh::cell(event.clone());
135 let interrupt = Interrupt::from_cell(cell);
136 interrupt.deliver();
137 assert!(event.try_wait());
138 event = pal_event::Event::new();
139 interrupt.deliver();
140 assert!(!event.try_wait());
141 updater.set(event.clone()).await;
142 interrupt.deliver();
143 assert!(event.try_wait());
144 }
145}