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 {
36 Self::from_event(pal_event::Event::new())
38 }
39
40 pub fn from_event(event: pal_event::Event) -> Self {
44 Self {
45 inner: InterruptInner::Event(Arc::new(event)),
46 }
47 }
48
49 pub fn from_cell(cell: mesh::Cell<pal_event::Event>) -> Self {
54 Self {
55 inner: InterruptInner::Cell(Arc::new(cell)),
56 }
57 }
58
59 pub fn from_fn<F>(f: F) -> Self
64 where
65 F: 'static + Send + Sync + Fn(),
66 {
67 Self {
68 inner: InterruptInner::Fn(LocalOnly(Arc::new(f))),
69 }
70 }
71
72 pub fn deliver(&self) {
74 match &self.inner {
75 InterruptInner::Event(event) => event.signal(),
76 InterruptInner::Cell(cell) => cell.with(|event| event.signal()),
77 InterruptInner::Fn(LocalOnly(f)) => f(),
78 }
79 }
80
81 pub fn event(&self) -> Option<&pal_event::Event> {
83 match &self.inner {
84 InterruptInner::Event(event) => Some(event.as_ref()),
85 _ => None,
86 }
87 }
88}
89
90#[derive(Clone, MeshPayload)]
91enum InterruptInner {
92 Event(Arc<pal_event::Event>),
93 Cell(Arc<mesh::Cell<pal_event::Event>>),
94 Fn(LocalOnly<Arc<dyn Send + Sync + Fn()>>),
95}
96
97impl Debug for InterruptInner {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 match self {
100 InterruptInner::Event(_) => f.pad("Event"),
101 InterruptInner::Cell(_) => f.pad("Cell"),
102 InterruptInner::Fn(_) => f.pad("Fn"),
103 }
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::Interrupt;
110 use pal_async::async_test;
111
112 #[test]
113 fn test_interrupt_event() {
114 let event = pal_event::Event::new();
115 let interrupt = Interrupt::from_event(event.clone());
116 interrupt.deliver();
117 assert!(event.try_wait());
118 }
119
120 #[async_test]
121 async fn test_interrupt_cell() {
122 let mut event = pal_event::Event::new();
123 let (mut updater, cell) = mesh::cell(event.clone());
124 let interrupt = Interrupt::from_cell(cell);
125 interrupt.deliver();
126 assert!(event.try_wait());
127 event = pal_event::Event::new();
128 interrupt.deliver();
129 assert!(!event.try_wait());
130 updater.set(event.clone()).await;
131 interrupt.deliver();
132 assert!(event.try_wait());
133 }
134}