Skip to main content

dope_runtime/executor/raw/
park.rs

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