1use std::{convert, mem, num::NonZero, pin};
4
5use dope_core::driver::{
6 self,
7 life::{self, finish},
8 retained, schedule,
9};
10use o3::base::{
11 cell::region,
12 num::bounded::{self, U32},
13};
14
15use crate::executor;
16
17mod activate;
18mod app;
19mod cursor;
20mod dispatch;
21mod owner;
22mod park;
23mod progress;
24mod released;
25
26pub use activate::Activate;
27pub use app::{App, Layout};
28pub use cursor::Cursor;
29pub use dispatch::Dispatch;
30pub(crate) use owner::{Backing, Draining, Live, Owner, Parent, View};
31pub use park::Park;
32pub use progress::Progress;
33pub use released::Released;
34
35pub unsafe trait Drain<'d>: executor::raw::App<'d> {
43 fn begin(
44 self: pin::Pin<&mut Self>,
45 turn: schedule::Turn<'_, 'd>,
46 driver: &mut retained::Context<'_, '_, 'd>,
47 );
48
49 fn progress(
50 self: pin::Pin<&Self>,
51 region: ®ion::Token<region::Identity<'d>>,
52 ) -> schedule::Progress<'d>;
53
54 fn force(
55 self: pin::Pin<&mut Self>,
56 turn: schedule::Turn<'_, 'd>,
57 driver: &mut retained::Context<'_, '_, 'd>,
58 );
59}
60
61pub struct Call<'app, R, P, O> {
63 app: pin::Pin<&'app mut R>,
64 plan: P,
65 op: O,
66}
67
68impl<'app, R, P, O> Call<'app, R, P, O> {
69 pub const fn new(app: pin::Pin<&'app mut R>, plan: P, op: O) -> Self {
71 Self { app, plan, op }
72 }
73
74 pub fn into_parts(self) -> (pin::Pin<&'app mut R>, P, O) {
75 (self.app, self.plan, self.op)
76 }
77
78 pub fn map_owner<U>(
80 self,
81 map: impl FnOnce(pin::Pin<&'app mut R>) -> pin::Pin<&'app mut U>,
82 ) -> Call<'app, U, P, O> {
83 Call {
84 app: map(self.app),
85 plan: self.plan,
86 op: self.op,
87 }
88 }
89}
90
91impl<R, O> Call<'_, R, convert::Infallible, O> {
92 pub fn into_never(self) -> ! {
94 match self {}
95 }
96}
97
98#[derive(Clone, Copy, Debug)]
100pub enum Count {
101 Bounded(U32<0, { schedule::LIMIT as u32 }>),
102 Excess(NonZero<usize>),
103}
104
105impl Count {
106 pub const fn new(value: usize) -> Self {
107 match U32::from_usize(value) {
108 Some(value) => Self::Bounded(value),
109 None => Self::Excess(NonZero::<usize>::MIN.saturating_add(value - 1)),
110 }
111 }
112
113 pub fn sum<const N: usize>(values: [usize; N]) -> Option<Self> {
114 values
115 .into_iter()
116 .try_fold(0usize, |count, value| count.checked_add(value))
117 .map(Self::new)
118 }
119
120 pub const fn get(self) -> usize {
121 match self {
122 Self::Bounded(value) => value.into_usize(),
123 Self::Excess(value) => value.get(),
124 }
125 }
126
127 pub(in crate::executor::raw) fn admit(self) -> Result<(), executor::InstallError> {
128 match self {
129 Self::Bounded(_) => Ok(()),
130 Self::Excess(count) => Err(executor::InstallError::Coordinators {
131 count,
132 limit: schedule::LIMIT,
133 }),
134 }
135 }
136}
137
138#[repr(transparent)]
140pub struct Weights<const N: usize> {
141 values: [U32<0, { schedule::LIMIT as u32 }>; N],
142}
143
144impl<const N: usize> Weights<N> {
145 pub const ZERO: Self = Self {
146 values: [U32::exact::<0>(); N],
147 };
148
149 pub fn prepare(&mut self, values: [usize; N]) -> Option<Count> {
150 let count = Count::sum(values)?;
151 if let Count::Bounded(_) = count {
152 self.values = values.map(|value| {
153 unsafe { bounded::raw::Proof::assume(value as u32) }.retain()
155 });
156 }
157 Some(count)
158 }
159
160 pub fn values(&self) -> [usize; N] {
161 self.values.map(U32::into_usize)
162 }
163}
164
165pub trait Finishes<'d, R = Self> {
166 fn call<'app, 'finish, 'owner, 'epoch>(
167 finish: Finish<'app, 'finish, 'owner, 'epoch, 'd, R>,
168 ) -> Finish<'app, 'finish, 'owner, 'epoch, 'd, R>;
169}
170
171#[must_use]
173pub struct Install<'app, 'owner, 'd, R> {
174 app: pin::Pin<&'app mut R>,
175 install: life::Install<'owner, 'd>,
176}
177
178#[must_use]
180pub struct Shutdown<'app, 'turn, 'driver, 'owner, 'd: 'owner, R> {
181 app: pin::Pin<&'app mut R>,
182 turn: schedule::Turn<'turn, 'd>,
183 driver: retained::Context<'driver, 'owner, 'd>,
184}
185
186#[must_use]
188pub struct Finish<'app, 'finish, 'owner, 'epoch, 'd, R> {
189 app: pin::Pin<&'app mut R>,
190 install: life::Install<'owner, 'd>,
191 finish: &'finish mut finish::Finish<'epoch, 'd>,
192}
193
194impl<'app, 'owner, 'd, R> Install<'app, 'owner, 'd, R> {
195 pub fn new(app: pin::Pin<&'app mut R>, install: life::Install<'owner, 'd>) -> Self {
196 Self { app, install }
197 }
198
199 pub fn into_parts(self) -> (pin::Pin<&'app mut R>, life::Install<'owner, 'd>) {
200 (self.app, self.install)
201 }
202
203 pub fn into_install(self) -> life::Install<'owner, 'd> {
204 self.install
205 }
206}
207
208impl<'app, 'turn, 'driver, 'owner, 'd: 'owner, R> Shutdown<'app, 'turn, 'driver, 'owner, 'd, R> {
209 pub fn new(
210 app: pin::Pin<&'app mut R>,
211 turn: schedule::Turn<'turn, 'd>,
212 driver: retained::Context<'driver, 'owner, 'd>,
213 ) -> Self {
214 Self { app, turn, driver }
215 }
216
217 pub fn into_parts(
218 self,
219 ) -> (
220 pin::Pin<&'app mut R>,
221 schedule::Turn<'turn, 'd>,
222 retained::Context<'driver, 'owner, 'd>,
223 ) {
224 (self.app, self.turn, self.driver)
225 }
226
227 pub fn into_drive(
228 self,
229 ) -> (
230 schedule::Turn<'turn, 'd>,
231 retained::Context<'driver, 'owner, 'd>,
232 ) {
233 (self.turn, self.driver)
234 }
235
236 pub(crate) fn into_driver(self) -> driver::Context<'driver, 'd> {
237 self.driver.into_driver()
238 }
239}
240
241impl<'app, 'finish, 'owner, 'epoch, 'd, R> Finish<'app, 'finish, 'owner, 'epoch, 'd, R> {
242 pub fn new(
243 app: pin::Pin<&'app mut R>,
244 install: life::Install<'owner, 'd>,
245 finish: &'finish mut finish::Finish<'epoch, 'd>,
246 ) -> Self {
247 Self {
248 app,
249 install,
250 finish,
251 }
252 }
253
254 pub fn into_parts(
255 self,
256 ) -> (
257 pin::Pin<&'app mut R>,
258 life::Install<'owner, 'd>,
259 &'finish mut finish::Finish<'epoch, 'd>,
260 ) {
261 (self.app, self.install, self.finish)
262 }
263
264 pub fn into_finish(
265 self,
266 ) -> (
267 life::Install<'owner, 'd>,
268 &'finish mut finish::Finish<'epoch, 'd>,
269 ) {
270 (self.install, self.finish)
271 }
272}
273
274struct Drive<'driver, 'turn, 'root, 'd: 'root> {
275 turn: schedule::Turn<'turn, 'd>,
276 driver: retained::Context<'driver, 'root, 'd>,
277}
278
279impl<'driver, 'turn, 'root, 'd: 'root> Drive<'driver, 'turn, 'root, 'd> {
280 const fn new(
281 turn: schedule::Turn<'turn, 'd>,
282 driver: retained::Context<'driver, 'root, 'd>,
283 ) -> Self {
284 Self { turn, driver }
285 }
286
287 fn reborrow(&mut self) -> Drive<'_, '_, 'root, 'd> {
288 Drive {
289 turn: self.turn.reborrow(),
290 driver: self.driver.reborrow(),
291 }
292 }
293
294 fn turn(&self) -> schedule::Turn<'_, 'd> {
295 self.turn.reborrow()
296 }
297
298 fn driver(&mut self) -> retained::Context<'_, 'root, 'd> {
299 self.driver.reborrow()
300 }
301
302 fn into_parts(
303 self,
304 ) -> (
305 schedule::Turn<'turn, 'd>,
306 retained::Context<'driver, 'root, 'd>,
307 ) {
308 (self.turn, self.driver)
309 }
310
311 fn into_driver(self) -> retained::Context<'driver, 'root, 'd> {
312 self.driver
313 }
314}
315
316const fn assert_layout() {
317 assert!(
318 mem::size_of::<Drive<'static, 'static, 'static, 'static>>() == 2 * mem::size_of::<usize>()
319 );
320 assert!(
321 mem::align_of::<Drive<'static, 'static, 'static, 'static>>() == mem::align_of::<usize>()
322 );
323 assert!(mem::size_of::<Install<'static, 'static, 'static, ()>>() == mem::size_of::<usize>());
324 assert!(
325 mem::size_of::<Shutdown<'static, 'static, 'static, 'static, 'static, ()>>()
326 == 3 * mem::size_of::<usize>()
327 );
328 assert!(
329 mem::size_of::<Finish<'static, 'static, 'static, 'static, 'static, ()>>()
330 == 2 * mem::size_of::<usize>()
331 );
332}
333
334const _: () = assert_layout();