tsuki_scheduler/runtime/
mod.rs1#[cfg(feature = "async-std")]
2mod async_std;
3use std::{future::Future, time::Duration};
4
5#[cfg(feature = "async-std")]
6pub use async_std::*;
7#[cfg(feature = "tokio")]
8mod tokio;
9#[cfg(feature = "tokio")]
10pub use tokio::*;
11#[cfg(feature = "thread")]
12mod thread;
13#[cfg(feature = "thread")]
14pub use thread::*;
15#[cfg(feature = "promise")]
16mod promise;
17#[cfg(feature = "promise")]
18pub use promise::*;
19
20mod local;
21pub use local::*;
22
23use crate::{Dtu, Task, TaskRun, TaskUid, prelude::IntoSchedule};
24
25pub trait Runtime {
26 type Handle;
27}
28
29pub trait AsyncRuntime: Runtime + Send + Sync {
30 fn wake_after(&self, duration: Duration, ctx: &mut std::task::Context<'_>);
32 fn spawn<F>(task: F) -> Self::Handle
33 where
34 F: Future<Output = ()> + Send + 'static;
35}
36
37impl<R: Runtime> Task<R> {
38 pub fn new<S, F, A>(schedule: S, run: F) -> Self
64 where
65 S: IntoSchedule,
66 F: IntoRunTaskFn<R, A>,
67 {
68 Self {
69 schedule: Box::new(schedule.into_schedule()),
70 run: Box::new(run.convert()),
71 }
72 }
73}
74impl<R: AsyncRuntime> Task<R> {
75 #[allow(private_bounds)]
77 pub fn new_async<S, F, A, Fut>(schedule: S, run: F) -> Self
78 where
79 S: IntoSchedule,
80 F: IntoRunTaskFn<R, Async<A, Fut>>,
81 {
82 Self {
83 schedule: Box::new(schedule.into_schedule()),
84 run: Box::new(run.convert()),
85 }
86 }
87}
88
89pub trait IntoRunTaskFn<R: Runtime, A> {
90 fn convert(self) -> impl Fn(&mut R, &TaskRun) -> <R as Runtime>::Handle + Send + 'static;
91}
92
93pub trait AsyncTaskFn<R: Runtime, A> {
94 type Future: std::future::Future<Output = ()> + Send + 'static;
95 fn convert(self) -> impl Fn(&mut R, &TaskRun) -> Self::Future;
96}
97
98pub trait TaskRunArg: Sized {
99 fn extract(task_run: &TaskRun) -> Self;
100}
101
102impl TaskRunArg for TaskRun {
103 fn extract(task_run: &TaskRun) -> Self {
104 task_run.clone()
105 }
106}
107
108impl TaskRunArg for TaskUid {
109 fn extract(task_run: &TaskRun) -> Self {
110 task_run.key
111 }
112}
113
114impl TaskRunArg for Dtu {
115 fn extract(task_run: &TaskRun) -> Self {
116 task_run.time
117 }
118}
119
120struct WithRuntime<A>(A);
121struct Async<A, F>(A, F);
122
123macro_rules! impl_for {
124 ($($T: ident)*) => {
125 impl_for!([][$($T)*]);
126 };
127 ([$($T: ident)*][$TN: ident $($Rest: ident)*]) => {
128 impl_for!(@impl [$($T)*]);
129 impl_for!([$($T)* $TN][$($Rest)*]);
130 };
131 ([$($T: ident)*][]) => {
132 impl_for!(@impl [$($T)*]);
133 };
134 (@impl [$($T: ident)*]) => {
135 impl<R, F, $($T,)*> IntoRunTaskFn<R, ($($T,)*)> for F
136 where
137 R: Runtime,
138 F: FnOnce($($T,)*) -> R::Handle + Send + 'static + Clone,
139 $($T: TaskRunArg,)*
140 {
141 #[allow(unused_variables)]
142 fn convert(
143 self,
144 ) -> impl Fn(&mut R, &TaskRun) -> <R as Runtime>::Handle + Send + 'static {
145 move |_, task_run| (self.clone())($($T::extract(task_run),)*)
146 }
147 }
148 impl<R, F, $($T,)*> IntoRunTaskFn<R, WithRuntime<($($T,)*)>> for F
149 where
150 R: Runtime,
151 F: FnOnce(&mut R, $($T,)*) -> R::Handle + Send + Sync + 'static + Clone,
152 $($T: TaskRunArg,)*
153 {
154 #[allow(unused_variables)]
155 fn convert(
156 self,
157 ) -> impl Fn(&mut R, &TaskRun) -> <R as Runtime>::Handle + Send+ 'static {
158 move |run_time, task_run| (self.clone())(run_time, $($T::extract(task_run),)*)
159 }
160 }
161 impl<R, F, Fut, $($T,)*> IntoRunTaskFn<R, Async<($($T,)*), Fut>> for F
162 where
163 R: AsyncRuntime,
164 F: FnOnce($($T,)*) -> Fut + Send + 'static + Clone,
165 Fut: std::future::Future<Output = ()> + Send + 'static ,
166 $($T: TaskRunArg,)*
167 {
168 #[allow(unused_variables)]
169 fn convert(
170 self,
171 ) -> impl Fn(&mut R, &TaskRun) -> <R as Runtime>::Handle + Send + 'static {
172 move |_, task_run| R::spawn((self.clone())($($T::extract(task_run),)*))
173 }
174 }
175 }
176}
177
178impl_for!(
179 T0 T1 T2 T3
180);