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 = ()>
17where
18 T: Send,
19{
20 inner: Arc<Inner<T>>,
21}
22
23impl<T> Clone for Payload<T>
24where
25 T: Send,
26{
27 fn clone(&self) -> Payload<T> {
28 Payload {
29 inner: self.inner.clone(),
30 }
31 }
32}
33
34impl<T> Payload<T>
35where
36 T: Send + 'static,
37{
38 pub fn new<S: std::fmt::Display>(id: S) -> Self {
41 let id = id.to_string();
42
43 let mut registry = REGISTRY.lock().unwrap();
44
45 if let Some(payload) = registry.get(&id) {
46 if let Some(p) = payload.downcast_ref::<Payload<T>>() {
47 let inner = p.inner.clone();
48 Self { inner }
49 } else {
50 panic!("Unable to downcast Payload `{id}`");
51 }
52 } else {
53 let inner = Arc::new(Inner {
54 id: id.clone(),
55 payload: Mutex::new(None),
56 pending: AtomicBool::new(false),
57 });
58
59 registry.insert(
60 id,
61 Box::new(Payload {
62 inner: inner.clone(),
63 }),
64 );
65 Self { inner }
66 }
67 }
68
69 pub fn store(&self, data: T) {
71 *self.inner.payload.lock().unwrap() = Some(data);
72 }
73
74 pub fn is_pending(&self) -> bool {
76 self.inner.pending.load(Ordering::SeqCst)
77 }
78
79 pub fn mark_pending(&self) {
81 self.inner.pending.store(true, Ordering::SeqCst);
82 }
83
84 pub fn clear_pending(&self) {
86 self.inner.pending.store(false, Ordering::SeqCst);
87 }
88
89 pub fn is_some(&self) -> bool {
91 self.inner.payload.lock().unwrap().is_some()
92 }
93
94 pub fn take(&self) -> Option<T> {
97 match self.inner.payload.lock().unwrap().take() {
98 Some(result) => {
99 self.clear_pending();
100 Some(result)
101 }
102 _ => None,
103 }
104 }
105
106 pub fn inner_clone(&self) -> Option<T>
109 where
110 T: Clone,
111 {
112 self.inner.payload.lock().unwrap().clone()
113 }
114}
115
116static REGISTRY: LazyLock<Mutex<HashMap<String, Box<dyn Any + Sync + Send>>>> =
117 LazyLock::new(|| Mutex::new(HashMap::new()));