Skip to main content

dope_core/driver/schedule/app/
step.rs

1use std::{marker, mem};
2
3use crate::driver::schedule::app;
4
5#[derive(Clone, Copy, Eq, PartialEq)]
6#[repr(u8)]
7pub enum Flow {
8    Batch,
9    Yield,
10}
11
12#[must_use = "delegated admission must authorize exactly one transition"]
13pub struct Delegated<'call, 'turn, 'd> {
14    call: marker::PhantomData<fn(&'call mut ()) -> &'call mut ()>,
15    brand: marker::PhantomData<app::Permit<'turn, 'd>>,
16}
17
18#[must_use = "delegated admission receipts must be settled"]
19pub struct Receipt<'turn, 'd> {
20    permit: app::Permit<'turn, 'd>,
21}
22
23pub trait Ready: Sized {
24    type Item;
25
26    fn rearm(self);
27
28    fn take(self) -> Self::Item;
29}
30
31pub struct Checkpoint<T, Take, Rearm> {
32    take: Take,
33    rearm: Rearm,
34    item: marker::PhantomData<fn() -> T>,
35}
36
37#[derive(Clone, Copy)]
38#[repr(transparent)]
39pub struct Step<'turn, 'd> {
40    work: app::Work<'turn, 'd>,
41}
42
43impl Delegated<'_, '_, '_> {
44    pub fn run<R>(self, f: impl FnOnce() -> R) -> R {
45        f()
46    }
47}
48
49impl<'turn, 'd> Receipt<'turn, 'd> {
50    pub const fn direct(permit: app::Permit<'turn, 'd>) -> Self {
51        Self { permit }
52    }
53
54    pub fn delegate<R>(
55        permit: app::Permit<'turn, 'd>,
56        run: impl for<'call> FnOnce(Delegated<'call, 'turn, 'd>) -> R,
57    ) -> (R, Self) {
58        let result = run(Delegated {
59            call: marker::PhantomData,
60            brand: marker::PhantomData,
61        });
62        (result, Self { permit })
63    }
64
65    pub fn settle(self, flow: Flow) -> Flow {
66        self.permit.run(|| flow)
67    }
68}
69
70impl<T, Take, Rearm> Checkpoint<T, Take, Rearm>
71where
72    Take: FnOnce() -> T,
73    Rearm: FnOnce(),
74{
75    pub const fn new(take: Take, rearm: Rearm) -> Self {
76        Self {
77            take,
78            rearm,
79            item: marker::PhantomData,
80        }
81    }
82}
83
84impl<T, Take, Rearm> Ready for Checkpoint<T, Take, Rearm>
85where
86    Take: FnOnce() -> T,
87    Rearm: FnOnce(),
88{
89    type Item = T;
90
91    fn rearm(self) {
92        (self.rearm)();
93    }
94
95    fn take(self) -> Self::Item {
96        (self.take)()
97    }
98}
99
100impl<'turn, 'd> Step<'turn, 'd> {
101    pub const fn new(work: app::Work<'turn, 'd>) -> Self {
102        Self { work }
103    }
104
105    pub fn batch<R: Ready>(self, ready: R) -> Option<R::Item> {
106        match self.work.permit() {
107            Some(permit) => Some(permit.run(|| ready.take())),
108            None => {
109                ready.rearm();
110                None
111            }
112        }
113    }
114}
115
116const _: () = {
117    assert!(mem::size_of::<Flow>() == 1);
118    assert!(mem::size_of::<Delegated<'static, 'static, 'static>>() == 0);
119    assert!(mem::size_of::<Receipt<'static, 'static>>() == 0);
120    assert!(mem::size_of::<Step<'static, 'static>>() == mem::size_of::<usize>());
121};