Skip to main content

dope_core/driver/schedule/
maint.rs

1use std::{marker, mem};
2
3use o3::{base::marker::ThreadBound, mem::quota};
4use state::lanes;
5
6use crate::driver::schedule::state;
7
8#[derive(Clone, Copy)]
9#[repr(transparent)]
10pub struct Work<'turn, 'd> {
11    pub(in crate::driver::schedule) state: &'turn state::Core<'d>,
12}
13
14#[must_use = "a maintenance permit represents one admitted transition"]
15pub struct Permit<'turn, 'd> {
16    proof: marker::PhantomData<(&'turn mut (), crate::driver::Invariant<'d>, ThreadBound)>,
17}
18
19impl<'turn, 'd> Work<'turn, 'd> {
20    pub fn remaining(self) -> usize {
21        self.state.lanes.maint.remaining()
22    }
23
24    pub fn run<T>(self, run: impl FnOnce() -> Option<T>) -> quota::Admission<T> {
25        self.state.lanes.maint.admit_with(run)
26    }
27
28    pub fn apply(self, run: impl FnOnce() -> quota::Acquire) {
29        self.state.lanes.maint.apply(run);
30    }
31
32    pub fn permit(self) -> Option<Permit<'turn, 'd>> {
33        match self.state.lanes.maint.take() {
34            quota::Take::Taken => Some(Permit::new()),
35            quota::Take::Exhausted => None,
36        }
37    }
38
39    pub fn claim<T>(
40        self,
41        claim: impl FnOnce() -> Option<T>,
42    ) -> quota::Admission<(T, Permit<'turn, 'd>)> {
43        self.run(|| claim().map(|value| (value, Permit::new())))
44    }
45
46    pub fn share<const N: usize, T>(self, run: impl FnOnce() -> T) -> T {
47        let _held = lanes::Quota::share::<N, _>(&self.state.lanes.maint, 0);
48        run()
49    }
50}
51
52impl<'turn, 'd> Permit<'turn, 'd> {
53    fn new() -> Self {
54        Self {
55            proof: marker::PhantomData,
56        }
57    }
58
59    pub fn run<T>(self, run: impl FnOnce() -> T) -> T {
60        run()
61    }
62}
63
64const _: () = {
65    let word = mem::size_of::<usize>();
66    assert!(mem::size_of::<Work<'static, 'static>>() == word);
67    assert!(mem::size_of::<Permit<'static, 'static>>() == 0);
68};