Skip to main content

dope_core/driver/life/
mod.rs

1use std::{marker, mem, pin};
2
3use dope_sys::memory::Context as _;
4pub(in crate::driver) use epochs::Final;
5use finish::Finish;
6use o3::{
7    base::{
8        cell::{brand, region},
9        marker::ThreadBound,
10    },
11    buffer,
12    buffer::storage::{provided, provided::fixed},
13};
14use plans::Provided;
15use schedule::state::Core;
16use state::scope;
17
18use crate::{
19    Engine, driver,
20    driver::{
21        life::recovery::{Observe, Recover},
22        retained::flight,
23        route::lease::Registry,
24        schedule,
25        schedule::state,
26        storage,
27        storage::{resident, resident::Alloc},
28    },
29    io,
30};
31
32pub mod creation;
33pub mod domain;
34pub mod finish;
35pub(crate) mod native;
36mod plans;
37pub mod recovery;
38
39/// Application completions still require ordinary driver dispatch before startup.
40#[derive(Clone, Copy, Debug, Eq, PartialEq)]
41pub struct Busy;
42
43/// Owner-bound primitives for generated installation roots.
44pub mod raw;
45
46/// Runs once inside the generation which owns a built storage output and source.
47pub trait Operation<S: storage::Plan, Q: ?Sized>: Sized {
48    type Output;
49
50    /// Reports storage rejection before native retirement.
51    fn rejected(&self, _source: &Q) {}
52
53    fn run<'a, 'p, 'd>(
54        self,
55        scope: Scope<'a, 'd>,
56        storage: storage::Loan<'a, 'p, 'd, S>,
57        source: &'a Q,
58    ) -> Self::Output
59    where
60        'd: 'p,
61        'p: 'a,
62        'd: 'a,
63        Self: 'd,
64        S: 'd,
65        Q: 'd;
66}
67
68/// Mutable driver-local authority owned by one generative scope.
69/// `driver::Context` lends this root as one pointer.
70pub(crate) struct Local<'d> {
71    pub(crate) driver: driver::Reference<'d>,
72    pub(crate) backend: fixed::Loan<'d, Engine>,
73    pub(in crate::driver) retry: bool,
74    pub(crate) flights: &'d mut flight::Arena,
75    pub(in crate::driver) resident: Alloc<'d>,
76    pub(in crate::driver) routes: Registry,
77    pub(in crate::driver) region: (
78        region::Token<region::Identity<'d>>,
79        region::Token<region::Identity<'d, 1>>,
80    ),
81    pub(crate) lifecycle: Lifecycle<'d>,
82}
83
84/// Generation-owned source and the policy responsible for its transitions.
85pub(crate) struct Lifecycle<'d> {
86    pub(crate) source: Option<dope_sys::engine::register::Source<'d>>,
87    pub(crate) resuming: bool,
88    pub(crate) pending: bool,
89    pub(crate) report: &'d mut dyn FnMut(io::Reclaimed),
90    pub(in crate::driver) recover: &'d dyn recovery::Recover,
91}
92
93impl Lifecycle<'_> {
94    pub(crate) fn report(&mut self, event: io::Reclaimed) {
95        if matches!(event, io::Reclaimed::Shutdown) {
96            let owned = self.source.take().is_some();
97            if self.resuming && owned {
98                self.pending = true;
99                return;
100            }
101        }
102        (self.report)(event);
103    }
104}
105
106pub(in crate::driver) struct State<'d> {
107    local: Local<'d>,
108    work: Core<'d>,
109    token: brand::Token<brand::Identity<'d>>,
110}
111
112impl<'d> State<'d> {
113    fn new(local: Local<'d>, token: brand::Token<brand::Identity<'d>>) -> Self {
114        Self {
115            work: Core::new(local.driver),
116            local,
117            token,
118        }
119    }
120}
121
122mod epochs;
123
124/// One lexical view of the hidden owner for an exact driver generation.
125///
126#[repr(transparent)]
127pub struct Scope<'a, 'd> {
128    state: &'a mut State<'d>,
129}
130
131impl<'a, 'd> Scope<'a, 'd> {
132    fn new(state: &'a mut State<'d>) -> Self {
133        Self { state }
134    }
135
136    pub fn context(&mut self) -> driver::Context<'_, 'd> {
137        let state = &mut *self.state;
138        driver::Context::new(&mut state.local)
139    }
140
141    pub fn token(&mut self) -> &mut brand::Token<brand::Identity<'d>> {
142        &mut self.state.token
143    }
144
145    #[inline]
146    pub fn split(
147        &mut self,
148    ) -> (
149        &mut brand::Token<brand::Identity<'d>>,
150        driver::Context<'_, 'd>,
151        scope::Scope<'_, 'd>,
152    ) {
153        let state = &mut *self.state;
154        let ctx = driver::Context::new(&mut state.local);
155        (&mut state.token, ctx, scope::Scope::new(&mut state.work))
156    }
157
158    pub fn driver_ref(&self) -> driver::Reference<'d> {
159        self.state.local.driver
160    }
161
162    /// Admits startup polling before any application completion can be emitted.
163    /// Keep exclusive scope authority and do not submit operations during startup.
164    pub fn try_boot(&self) -> Result<(), Busy> {
165        if self.state.local.flights.is_pending() {
166            Err(Busy)
167        } else {
168            Ok(())
169        }
170    }
171
172    /// Drains every retained operation before captured owners may be released.
173    /// A failed native transition retains its owner and invokes the fatal policy.
174    /// Only successful native quiescence permits the borrowed scope to return.
175    pub fn quiesce(&mut self) {
176        let state = &mut *self.state;
177        let ctx = driver::Context::new(&mut state.local);
178        Final::suspend(ctx).resume()
179    }
180
181    /// Quiesces before lending finish authority, then reaps the released owner.
182    /// A failed transition invokes the fatal policy with the exact native owner.
183    #[doc(hidden)]
184    pub fn finish<R>(
185        &mut self,
186        forced: bool,
187        run: impl for<'finish> FnOnce(
188            &mut brand::Token<brand::Identity<'d>>,
189            &mut Finish<'finish, 'd>,
190        ) -> R,
191    ) -> R {
192        let state = &mut *self.state;
193        let ctx = driver::Context::new(&mut state.local);
194        let last = Final::suspend(ctx);
195        let mut finish = Finish::new(last, forced);
196        let output = run(&mut state.token, &mut finish);
197        finish.resume();
198        output
199    }
200}
201
202impl driver::Driver {
203    fn run_scope<A, Q: ?Sized, O>(
204        &mut self,
205        arenas: A,
206        source: &domain::Source<Q>,
207        op: O,
208        report: &mut dyn Observe,
209    ) -> O::Output
210    where
211        A: buffer::raw::Arenas,
212        O: Operation<storage::Scope<A>, Q>,
213    {
214        let runtime = &mut self.runtime;
215        let (report, recover) = report.split();
216        let root = Root {
217            flights: &mut runtime.flights,
218            resident: &mut runtime.resident,
219            source,
220            report,
221            recover,
222        };
223        runtime.shared.run(
224            pin::pin!((root, arenas)),
225            runtime.shared.context().buffer().layout().0.accounts(),
226            &mut runtime.backend,
227            Provided(op),
228        )
229    }
230
231    fn scope<'b, Q: ?Sized, O>(
232        &'b mut self,
233        source: &'b domain::Source<Q>,
234        op: O,
235        report: &'b mut dyn Observe,
236    ) -> O::Output
237    where
238        O: fixed::Operation<Root<'b, Q>, driver::Buffer, driver::Shared, Terminal = crate::Engine>,
239    {
240        let runtime = &mut self.runtime;
241        let (report, recover) = report.split();
242        let root = Root {
243            flights: &mut runtime.flights,
244            resident: &mut runtime.resident,
245            source,
246            report,
247            recover,
248        };
249        runtime.shared.run(
250            pin::pin!(root),
251            runtime.shared.context().buffer().layout().0.accounts(),
252            &mut runtime.backend,
253            op,
254        )
255    }
256}
257
258const _: () = {
259    assert!(mem::size_of::<Scope<'static, 'static>>() == mem::size_of::<&mut ()>());
260    assert!(mem::align_of::<Scope<'static, 'static>>() == mem::align_of::<&mut ()>());
261};
262
263struct Root<'a, Q: ?Sized> {
264    flights: &'a mut flight::Arena,
265    resident: &'a mut resident::Arena,
266    source: &'a domain::Source<Q>,
267    report: &'a mut dyn FnMut(io::Reclaimed),
268    recover: &'a dyn Recover,
269}
270
271impl<Q: ?Sized> Root<'_, Q> {
272    fn enter<'d>(
273        &'d mut self,
274        shared: provided::Root<'d, driver::Buffer, driver::Shared, ()>,
275        token: brand::Token<brand::Identity<'d>>,
276        regions: (
277            region::Token<region::Identity<'d>>,
278            region::Token<region::Identity<'d, 1>>,
279        ),
280        backend: fixed::Loan<'d, Engine>,
281    ) -> (State<'d>, &'d Q) {
282        let alloc = self.resident.enter(&regions.0);
283        let local = Local {
284            driver: driver::Reference::new(shared),
285            backend,
286            retry: false,
287            flights: &mut *self.flights,
288            resident: alloc,
289            routes: Registry::new(),
290            region: regions,
291            lifecycle: Lifecycle {
292                source: self.source.descriptor(),
293                resuming: false,
294                pending: false,
295                report: &mut *self.report,
296                recover: self.recover,
297            },
298        };
299        let state = State::new(local, token);
300        (state, &self.source.value)
301    }
302}
303
304/// Proof that nested resources are installed beneath their pinned owner.
305#[must_use]
306pub struct Install<'a, 'd> {
307    owner: marker::PhantomData<(&'a mut raw::Anchor<'a>, ThreadBound)>,
308    _driver: driver::Invariant<'d>,
309}
310
311impl<'a, 'd> Install<'a, 'd> {
312    /// Binds installation to `root` and its driver generation.
313    pub fn new<T: raw::Root<'a>>(root: T, driver: driver::Reference<'d>) -> Self {
314        Self {
315            owner: root.anchor().owner(),
316            _driver: driver.brand,
317        }
318    }
319}
320
321const _: () = {
322    assert!(mem::size_of::<Install<'static, 'static>>() == 0);
323    assert!(mem::align_of::<Install<'static, 'static>>() == 1);
324};