fret_runtime/
execution.rs1use std::{sync::Arc, time::Duration};
2
3use fret_core::AppWindowId;
4
5use crate::ExecCapabilities;
6use crate::effect::Effect;
7use crate::model::ModelStore;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum DispatchPriority {
11 Low,
12 Normal,
13 High,
14}
15
16pub type Runnable = Box<dyn FnOnce() + Send + 'static>;
17
18pub trait Dispatcher: Send + Sync + 'static {
26 fn dispatch_on_main_thread(&self, task: Runnable);
28
29 fn dispatch_background(&self, task: Runnable, priority: DispatchPriority);
35
36 fn dispatch_after(&self, delay: Duration, task: Runnable);
41
42 fn wake(&self, window: Option<AppWindowId>);
47
48 fn exec_capabilities(&self) -> ExecCapabilities;
50}
51
52pub type DispatcherHandle = Arc<dyn Dispatcher>;
53
54pub trait InboxDrainHost {
55 fn request_redraw(&mut self, window: AppWindowId);
56 fn push_effect(&mut self, effect: Effect);
57 fn models_mut(&mut self) -> &mut ModelStore;
58}
59
60pub trait InboxDrain: Send + Sync + 'static {
61 fn drain(&self, host: &mut dyn InboxDrainHost, window: Option<AppWindowId>) -> bool;
62}
63
64#[derive(Default)]
65pub struct InboxDrainRegistry {
66 drainers: Vec<Arc<dyn InboxDrain>>,
67}
68
69impl InboxDrainRegistry {
70 pub fn register(&mut self, drainer: Arc<dyn InboxDrain>) {
71 self.drainers.push(drainer);
72 }
73
74 pub fn drain_all(&self, host: &mut dyn InboxDrainHost, window: Option<AppWindowId>) -> bool {
75 let mut did_work = false;
76 for drainer in &self.drainers {
77 did_work |= drainer.drain(host, window);
78 }
79 did_work
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[derive(Default)]
88 struct TestHost {
89 models: ModelStore,
90 redraws: Vec<AppWindowId>,
91 effects: Vec<Effect>,
92 }
93
94 impl InboxDrainHost for TestHost {
95 fn request_redraw(&mut self, window: AppWindowId) {
96 self.redraws.push(window);
97 }
98
99 fn push_effect(&mut self, effect: Effect) {
100 self.effects.push(effect);
101 }
102
103 fn models_mut(&mut self) -> &mut ModelStore {
104 &mut self.models
105 }
106 }
107
108 #[test]
109 fn inbox_drain_registry_invokes_drainers_and_reports_progress() {
110 struct Drainer;
111 impl InboxDrain for Drainer {
112 fn drain(&self, _host: &mut dyn InboxDrainHost, _window: Option<AppWindowId>) -> bool {
113 true
114 }
115 }
116
117 let mut host = TestHost::default();
118 let mut reg = InboxDrainRegistry::default();
119 reg.register(Arc::new(Drainer));
120
121 assert!(reg.drain_all(&mut host, None));
122 }
123}