dope_core/driver/schedule/app/
step.rs1use 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};