Skip to main content

dope_runtime/executor/raw/
park.rs

1use std::{mem, pin};
2
3use dope_core::driver::{
4    retained,
5    schedule::{self, clock},
6};
7use o3::mem::quota;
8
9use crate::{control, executor};
10
11/// Pre-park authority for one exact retained root and scheduler turn.
12#[must_use]
13pub struct Park<'driver, 'turn, 'root, 'd: 'root> {
14    drive: executor::raw::Drive<'driver, 'turn, 'root, 'd>,
15}
16
17impl<'driver, 'turn, 'root, 'd: 'root> Park<'driver, 'turn, 'root, 'd> {
18    pub(crate) const fn new(
19        turn: schedule::Turn<'turn, 'd>,
20        driver: retained::Context<'driver, 'root, 'd>,
21    ) -> Self {
22        Self {
23            drive: executor::raw::Drive { turn, driver },
24        }
25    }
26
27    pub fn reborrow(&mut self) -> Park<'_, '_, 'root, 'd> {
28        Park {
29            drive: self.drive.reborrow(),
30        }
31    }
32
33    pub fn map<R>(
34        self,
35        map: impl FnOnce(schedule::Turn<'turn, 'd>, retained::Context<'driver, 'root, 'd>) -> R,
36    ) -> R {
37        let executor::raw::Drive { turn, driver } = self.drive;
38        map(turn, driver)
39    }
40
41    pub fn into_driver(self) -> retained::Context<'driver, 'root, 'd> {
42        self.drive.driver
43    }
44
45    pub(crate) fn run<R>(self, app: pin::Pin<&mut R>, plan: &mut Option<R::ParkPlan>)
46    where
47        R: executor::raw::App<'d>,
48    {
49        if let Some(plan) = plan {
50            // SAFETY: publication prepared this plan for the same installed pinned root.
51            // Failed admission runs forced finish without entering a park operation.
52            unsafe { R::park(app, plan, self) }
53        }
54    }
55
56    pub fn app_cursor<const N: usize>(
57        &self,
58        cursor: &mut executor::raw::Cursor<N>,
59    ) -> executor::raw::Cursor<N> {
60        cursor.start(self.drive.turn.app().remaining())
61    }
62
63    pub fn maint_cursor<const N: usize>(
64        &self,
65        cursor: &mut executor::raw::Cursor<N>,
66    ) -> executor::raw::Cursor<N> {
67        cursor.start(self.drive.turn.maint().remaining())
68    }
69
70    pub fn coord_cursor<const N: usize>(
71        &self,
72        cursor: &mut executor::raw::Cursor<N>,
73    ) -> executor::raw::Cursor<N> {
74        cursor.start(self.drive.turn.coord().remaining())
75    }
76
77    pub fn coord_left(&self) -> usize {
78        self.drive.turn.coord().remaining()
79    }
80
81    pub fn share<const N: usize, R>(
82        &mut self,
83        ranks: [usize; 3],
84        weights: [usize; 2],
85        run: impl FnOnce(Park<'_, '_, 'root, 'd>) -> R,
86    ) -> R {
87        self.drive.turn.share::<N, _>(ranks, weights, |turn| {
88            let drive = executor::raw::Drive {
89                turn,
90                driver: self.drive.driver.reborrow(),
91            };
92            run(Park { drive })
93        })
94    }
95
96    pub fn share_coord<const N: usize, R>(
97        &mut self,
98        rank: usize,
99        weights: [usize; 2],
100        run: impl FnOnce(Park<'_, '_, 'root, 'd>) -> R,
101    ) -> R {
102        self.drive
103            .turn
104            .coord()
105            .share::<N, _>(rank, weights, || run(self.reborrow()))
106    }
107
108    /// Monotonic time captured once at the beginning of this driver turn.
109    pub fn now(&mut self) -> clock::Moment<'d> {
110        self.drive.driver.reborrow().driver_ref().clock().now()
111    }
112
113    /// Admits one step whose clock and region authorities share this borrow.
114    pub fn next_step(&mut self) -> Option<control::Step<'_, 'd>> {
115        match self.drive.turn.reborrow().coord().take() {
116            quota::Take::Taken => {}
117            quota::Take::Exhausted => return None,
118        }
119        let driver = self.drive.driver.reborrow().into_driver();
120        Some(control::Step::new(driver))
121    }
122}
123
124const fn assert_layout() {
125    type Turn<'a> = Park<'a, 'a, 'a, 'a>;
126
127    assert!(mem::size_of::<Turn<'static>>() == 2 * mem::size_of::<usize>());
128    assert!(mem::align_of::<Turn<'static>>() == mem::align_of::<usize>());
129}
130
131const _: () = assert_layout();