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(
55 self: pin::Pin<&Self>,
56 region: ®ion::Token<region::Identity<'d>>,
57 ) -> schedule::Progress<'d>;
58
59 fn force(
60 self: pin::Pin<&mut Self>,
61 turn: schedule::Turn<'_, 'd>,
62 driver: &mut retained::Context<'_, '_, 'd>,
63 );
64}
65
66pub struct Call<'app, R, P, O> {
68 app: pin::Pin<&'app mut R>,
69 plan: P,
70 op: O,
71}
72
73impl<'app, R, P, O> Call<'app, R, P, O> {
74 pub const fn new(app: pin::Pin<&'app mut R>, plan: P, op: O) -> Self {
76 Self { app, plan, op }
77 }
78
79 pub fn into_parts(self) -> (pin::Pin<&'app mut R>, P, O) {
80 (self.app, self.plan, self.op)
81 }
82
83 pub fn map_owner<U>(
85 self,
86 map: impl FnOnce(pin::Pin<&'app mut R>) -> pin::Pin<&'app mut U>,
87 ) -> Call<'app, U, P, O> {
88 Call {
89 app: map(self.app),
90 plan: self.plan,
91 op: self.op,
92 }
93 }
94}
95
96impl<R, O> Call<'_, R, convert::Infallible, O> {
97 pub fn into_never(self) -> ! {
99 match self {}
100 }
101}
102
103#[derive(Clone, Copy, Debug)]
105pub enum Count {
106 Bounded(U32<0, { schedule::LIMIT as u32 }>),
107 Excess(NonZero<usize>),
108}
109
110impl Count {
111 pub const fn new(value: usize) -> Self {
112 match U32::from_usize(value) {
113 Some(value) => Self::Bounded(value),
114 None => Self::Excess(NonZero::<usize>::MIN.saturating_add(value - 1)),
115 }
116 }
117
118 pub fn sum<const N: usize>(values: [usize; N]) -> Option<Self> {
119 values
120 .into_iter()
121 .try_fold(0usize, |count, value| count.checked_add(value))
122 .map(Self::new)
123 }
124
125 pub const fn get(self) -> usize {
126 match self {
127 Self::Bounded(value) => value.into_usize(),
128 Self::Excess(value) => value.get(),
129 }
130 }
131
132 pub(in crate::executor::raw) fn admit(self) -> Result<(), executor::InstallError> {
133 match self {
134 Self::Bounded(_) => Ok(()),
135 Self::Excess(count) => Err(executor::InstallError::Coordinators {
136 count,
137 limit: schedule::LIMIT,
138 }),
139 }
140 }
141}
142
143#[repr(transparent)]
145pub struct Weights<const N: usize> {
146 values: [U32<0, { schedule::LIMIT as u32 }>; N],
147}
148
149impl<const N: usize> Weights<N> {
150 pub const ZERO: Self = Self {
151 values: [U32::exact::<0>(); N],
152 };
153
154 pub fn prepare(&mut self, values: [usize; N]) -> Option<Count> {
155 let count = Count::sum(values)?;
156 if let Count::Bounded(_) = count {
157 self.values = values.map(|value| {
158 unsafe { bounded::raw::Proof::assume(value as u32) }.retain()
160 });
161 }
162 Some(count)
163 }
164
165 pub fn values(&self) -> [usize; N] {
166 self.values.map(U32::into_usize)
167 }
168}
169
170pub trait Finishes<'d, R = Self> {
171 fn call<'app, 'finish, 'owner, 'epoch>(
172 finish: Finish<'app, 'finish, 'owner, 'epoch, 'd, R>,
173 ) -> Finish<'app, 'finish, 'owner, 'epoch, 'd, R>;
174}
175
176#[must_use]
178pub struct Install<'app, 'owner, 'd, R> {
179 app: pin::Pin<&'app mut R>,
180 install: life::Install<'owner, 'd>,
181}
182
183#[must_use]
185pub struct Shutdown<'app, 'turn, 'driver, 'owner, 'd: 'owner, R> {
186 app: pin::Pin<&'app mut R>,
187 turn: schedule::Turn<'turn, 'd>,
188 driver: retained::Context<'driver, 'owner, 'd>,
189}
190
191#[must_use]
193pub struct Finish<'app, 'finish, 'owner, 'epoch, 'd, R> {
194 app: pin::Pin<&'app mut R>,
195 install: life::Install<'owner, 'd>,
196 finish: &'finish mut finish::Finish<'epoch, 'd>,
197}
198
199impl<'app, 'owner, 'd, R> Install<'app, 'owner, 'd, R> {
200 pub fn new(app: pin::Pin<&'app mut R>, install: life::Install<'owner, 'd>) -> Self {
201 Self { app, install }
202 }
203
204 pub fn into_parts(self) -> (pin::Pin<&'app mut R>, life::Install<'owner, 'd>) {
205 (self.app, self.install)
206 }
207
208 pub fn into_install(self) -> life::Install<'owner, 'd> {
209 self.install
210 }
211}
212
213impl<'app, 'turn, 'driver, 'owner, 'd: 'owner, R> Shutdown<'app, 'turn, 'driver, 'owner, 'd, R> {
214 pub fn new(
215 app: pin::Pin<&'app mut R>,
216 turn: schedule::Turn<'turn, 'd>,
217 driver: retained::Context<'driver, 'owner, 'd>,
218 ) -> Self {
219 Self { app, turn, driver }
220 }
221
222 pub fn into_parts(
223 self,
224 ) -> (
225 pin::Pin<&'app mut R>,
226 schedule::Turn<'turn, 'd>,
227 retained::Context<'driver, 'owner, 'd>,
228 ) {
229 (self.app, self.turn, self.driver)
230 }
231
232 pub fn into_drive(
233 self,
234 ) -> (
235 schedule::Turn<'turn, 'd>,
236 retained::Context<'driver, 'owner, 'd>,
237 ) {
238 (self.turn, self.driver)
239 }
240
241 pub(crate) fn into_driver(self) -> driver::Context<'driver, 'd> {
242 self.driver.into_driver()
243 }
244}
245
246impl<'app, 'finish, 'owner, 'epoch, 'd, R> Finish<'app, 'finish, 'owner, 'epoch, 'd, R> {
247 pub fn new(
248 app: pin::Pin<&'app mut R>,
249 install: life::Install<'owner, 'd>,
250 finish: &'finish mut finish::Finish<'epoch, 'd>,
251 ) -> Self {
252 Self {
253 app,
254 install,
255 finish,
256 }
257 }
258
259 pub fn into_parts(
260 self,
261 ) -> (
262 pin::Pin<&'app mut R>,
263 life::Install<'owner, 'd>,
264 &'finish mut finish::Finish<'epoch, 'd>,
265 ) {
266 (self.app, self.install, self.finish)
267 }
268
269 pub fn into_finish(
270 self,
271 ) -> (
272 life::Install<'owner, 'd>,
273 &'finish mut finish::Finish<'epoch, 'd>,
274 ) {
275 (self.install, self.finish)
276 }
277}
278
279struct Drive<'driver, 'turn, 'root, 'd: 'root> {
280 turn: schedule::Turn<'turn, 'd>,
281 driver: retained::Context<'driver, 'root, 'd>,
282}
283
284impl<'driver, 'turn, 'root, 'd: 'root> Drive<'driver, 'turn, 'root, 'd> {
285 fn reborrow(&mut self) -> Drive<'_, '_, 'root, 'd> {
286 Drive {
287 turn: self.turn.reborrow(),
288 driver: self.driver.reborrow(),
289 }
290 }
291}
292
293const fn assert_layout() {
294 assert!(
295 mem::size_of::<Drive<'static, 'static, 'static, 'static>>() == 2 * mem::size_of::<usize>()
296 );
297 assert!(
298 mem::align_of::<Drive<'static, 'static, 'static, 'static>>() == mem::align_of::<usize>()
299 );
300 assert!(mem::size_of::<Install<'static, 'static, 'static, ()>>() == mem::size_of::<usize>());
301 assert!(
302 mem::size_of::<Shutdown<'static, 'static, 'static, 'static, 'static, ()>>()
303 == 3 * mem::size_of::<usize>()
304 );
305 assert!(
306 mem::size_of::<Finish<'static, 'static, 'static, 'static, 'static, ()>>()
307 == 2 * mem::size_of::<usize>()
308 );
309}
310
311const _: () = assert_layout();