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#[derive(Clone, Copy, Debug, Eq, PartialEq)]
41pub struct Busy;
42
43pub mod raw;
45
46pub trait Operation<S: storage::Plan, Q: ?Sized>: Sized {
48 type Output;
49
50 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
68pub(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
84pub(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#[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 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 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 #[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(®ions.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#[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 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};