workflow_egui/runtime/
payload.rs

1use 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()));