workflow_egui/runtime/
payload.rs1use crate::imports::*;
2
3struct Inner<T>
4where
5 T: Send,
6{
7 #[allow(dead_code)]
8 id: String,
9 payload: Mutex<Option<T>>,
10 pending: AtomicBool,
11}
12
13pub struct Payload<T = ()>
14where
15 T: Send,
16{
17 inner: Arc<Inner<T>>,
18}
19
20impl<T> Clone for Payload<T>
21where
22 T: Send,
23{
24 fn clone(&self) -> Payload<T> {
25 Payload {
26 inner: self.inner.clone(),
27 }
28 }
29}
30
31impl<T> Payload<T>
32where
33 T: Send + 'static,
34{
35 pub fn new<S: std::fmt::Display>(id: S) -> Self {
36 let id = id.to_string();
37
38 let mut registry = REGISTRY.lock().unwrap();
39
40 if let Some(payload) = registry.get(&id) {
41 if let Some(p) = payload.downcast_ref::<Payload<T>>() {
42 let inner = p.inner.clone();
43 Self { inner }
44 } else {
45 panic!("Unable to downcast Payload `{id}`");
46 }
47 } else {
48 let inner = Arc::new(Inner {
49 id: id.clone(),
50 payload: Mutex::new(None),
51 pending: AtomicBool::new(false),
52 });
53
54 registry.insert(
55 id,
56 Box::new(Payload {
57 inner: inner.clone(),
58 }),
59 );
60 Self { inner }
61 }
62 }
63
64 pub fn store(&self, data: T) {
65 *self.inner.payload.lock().unwrap() = Some(data);
66 }
67
68 pub fn is_pending(&self) -> bool {
69 self.inner.pending.load(Ordering::SeqCst)
70 }
71
72 pub fn mark_pending(&self) {
73 self.inner.pending.store(true, Ordering::SeqCst);
74 }
75
76 pub fn clear_pending(&self) {
77 self.inner.pending.store(false, Ordering::SeqCst);
78 }
79
80 pub fn is_some(&self) -> bool {
81 self.inner.payload.lock().unwrap().is_some()
82 }
83
84 pub fn take(&self) -> Option<T> {
85 if let Some(result) = self.inner.payload.lock().unwrap().take() {
86 self.clear_pending();
87 Some(result)
88 } else {
89 None
90 }
91 }
92
93 pub fn inner_clone(&self) -> Option<T>
94 where
95 T: Clone,
96 {
97 self.inner.payload.lock().unwrap().clone().take()
98 }
99}
100
101static REGISTRY: LazyLock<Mutex<HashMap<String, Box<dyn Any + Sync + Send>>>> =
102 LazyLock::new(|| Mutex::new(HashMap::new()));