1use std::{
2 convert::Infallible,
3 sync::{Arc, RwLock},
4};
5
6use crate::{
7 client::MistyClientHandle,
8 controllers::MistyControllerContext,
9 signals::{MistySignal, SignalEmitter},
10};
11
12pub(crate) struct ScheduleManager {
13 tasks: Arc<RwLock<Vec<ScheduledTask>>>,
14}
15
16pub(crate) struct ScheduledTask {
17 handler: Box<dyn FnOnce(MistyClientHandle) + Send + Sync>,
18}
19
20impl ScheduledTask {
21 fn new<E>(
22 handler: impl FnOnce(MistyClientHandle) -> Result<(), E> + Send + Sync + 'static,
23 ) -> Self
24 where
25 E: std::fmt::Display,
26 {
27 Self {
28 handler: Box::new(|handle| {
29 let err = handler(handle);
30 if let Err(err) = err {
31 tracing::error!("schedule fail, error: {}", err);
32 }
33 }),
34 }
35 }
36
37 fn run(self, handle: MistyClientHandle) {
38 (self.handler)(handle);
39 }
40}
41
42impl ScheduleManager {
43 pub fn new() -> Self {
44 Self {
45 tasks: Default::default(),
46 }
47 }
48
49 pub fn enqueue<E>(
50 &self,
51 signal_emitter: &SignalEmitter,
52 handler: impl FnOnce(MistyClientHandle) -> Result<(), E> + Send + Sync + 'static,
53 ) where
54 E: std::fmt::Display,
55 {
56 {
57 let mut tasks = self.tasks.write().unwrap();
58 tasks.push(ScheduledTask::new(handler));
59 }
60 signal_emitter.emit(MistySignal::Schedule);
61 }
62
63 pub fn take_all_tasks(&self) -> Vec<ScheduledTask> {
64 let mut current_tasks = vec![];
65 {
66 let mut tasks = self.tasks.write().unwrap();
67 std::mem::swap::<Vec<ScheduledTask>>(&mut *tasks, current_tasks.as_mut());
68 }
69 current_tasks
70 }
71}
72
73pub(crate) fn controller_flush_scheduled_tasks(
74 ctx: MistyControllerContext,
75 _arg: (),
76) -> Result<(), Infallible> {
77 let handle = ctx.handle();
78 let tasks = handle.inner.schedule_manager.take_all_tasks();
79
80 for task in tasks.into_iter() {
81 task.run(handle.clone());
82 }
83
84 Ok(())
85}