1use std::{convert, mem, num::NonZero, pin};
4
5use dope_core::driver::{
6 life::{self, finish},
7 retained, schedule,
8};
9use o3::base::{
10 cell::region,
11 num::bounded::{self, U32},
12};
13
14use crate::executor;
15
16mod activate;
17mod app;
18mod cursor;
19mod dispatch;
20mod owner;
21mod park;
22mod progress;
23mod released;
24
25pub use activate::Activate;
26pub use app::{App, Layout};
27pub use cursor::Cursor;
28pub use dispatch::Dispatch;
29pub(crate) use owner::{Backing, Draining, Live, Owner, Parent, View};
30pub use park::Park;
31pub use progress::Progress;
32pub use released::Released;
33
34pub unsafe trait Drain<'d>: executor::raw::App<'d> {
42 fn begin(
43 self: pin::Pin<&mut Self>,
44 turn: schedule::Turn<'_, 'd>,
45 driver: &mut retained::Context<'_, '_, 'd>,
46 );
47
48 fn progress(
54 self: pin::Pin<&Self>,
55 region: ®ion::Token<region::Identity<'d>>,
56 ) -> schedule::Progress<'d>;
57
58 fn force(
59 self: pin::Pin<&mut Self>,
60 turn: schedule::Turn<'_, 'd>,
61 driver: &mut retained::Context<'_, '_, 'd>,
62 );
63}
64
65pub struct Call<'app, R, P, O> {
67 app: pin::Pin<&'app mut R>,
68 plan: P,
69 op: O,
70}
71
72impl<'app, R, P, O> Call<'app, R, P, O> {
73 pub const fn new(app: pin::Pin<&'app mut R>, plan: P, op: O) -> Self {
75 Self { app, plan, op }
76 }
77
78 pub fn into_parts(self) -> (pin::Pin<&'app mut R>, P, O) {
79 (self.app, self.plan, self.op)
80 }
81
82 pub fn map_owner<U>(
84 self,
85 map: impl FnOnce(pin::Pin<&'app mut R>) -> pin::Pin<&'app mut U>,
86 ) -> Call<'app, U, P, O> {
87 Call {
88 app: map(self.app),
89 plan: self.plan,
90 op: self.op,
91 }
92 }
93}
94
95impl<R, O> Call<'_, R, convert::Infallible, O> {
96 pub fn into_never(self) -> ! {
98 match self {}
99 }
100}
101
102#[derive(Clone, Copy, Debug)]
104pub enum Count {
105 Bounded(U32<0, { schedule::LIMIT as u32 }>),
106 Excess(NonZero<usize>),
107}
108
109impl Count {
110 pub const fn new(value: usize) -> Self {
111 match U32::from_usize(value) {
112 Some(value) => Self::Bounded(value),
113 None => Self::Excess(NonZero::<usize>::MIN.saturating_add(value - 1)),
114 }
115 }
116
117 pub fn sum<const N: usize>(values: [usize; N]) -> Option<Self> {
118 values
119 .into_iter()
120 .try_fold(0usize, |count, value| count.checked_add(value))
121 .map(Self::new)
122 }
123
124 pub const fn get(self) -> usize {
125 match self {
126 Self::Bounded(value) => value.into_usize(),
127 Self::Excess(value) => value.get(),
128 }
129 }
130
131 pub(in crate::executor::raw) fn admit(self) -> Result<(), executor::InstallError> {
132 match self {
133 Self::Bounded(_) => Ok(()),
134 Self::Excess(count) => Err(executor::InstallError::Coordinators {
135 count,
136 limit: schedule::LIMIT,
137 }),
138 }
139 }
140}
141
142#[repr(transparent)]
144pub struct Weights<const N: usize> {
145 values: [U32<0, { schedule::LIMIT as u32 }>; N],
146}
147
148impl<const N: usize> Weights<N> {
149 pub const ZERO: Self = Self {
150 values: [U32::exact::<0>(); N],
151 };
152
153 pub fn prepare(&mut self, values: [usize; N]) -> Option<Count> {
154 let count = Count::sum(values)?;
155 if let Count::Bounded(_) = count {
156 self.values = values.map(|value| {
157 unsafe { bounded::raw::u32(value as u32) }
159 });
160 }
161 Some(count)
162 }
163
164 pub fn values(&self) -> [usize; N] {
165 self.values.map(U32::into_usize)
166 }
167}
168
169pub trait Finishes<'d, R = Self> {
170 fn call<'app, 'finish, 'owner, 'epoch>(
171 finish: Finish<'app, 'finish, 'owner, 'epoch, 'd, R>,
172 ) -> Finish<'app, 'finish, 'owner, 'epoch, 'd, R>;
173}
174
175#[must_use]
177pub struct Install<'app, 'owner, 'd, R> {
178 app: pin::Pin<&'app mut R>,
179 install: life::Install<'owner, 'd>,
180}
181
182#[must_use]
184pub struct Shutdown<'app, 'turn, 'driver, 'owner, 'd: 'owner, R> {
185 app: pin::Pin<&'app mut R>,
186 turn: schedule::Turn<'turn, 'd>,
187 driver: retained::Context<'driver, 'owner, 'd>,
188}
189
190#[must_use]
192pub struct Finish<'app, 'finish, 'owner, 'epoch, 'd, R> {
193 app: pin::Pin<&'app mut R>,
194 install: life::Install<'owner, 'd>,
195 finish: &'finish mut finish::Finish<'epoch, 'd>,
196}
197
198impl<'app, 'owner, 'd, R> Install<'app, 'owner, 'd, R> {
199 pub fn new(app: pin::Pin<&'app mut R>, install: life::Install<'owner, 'd>) -> Self {
200 Self { app, install }
201 }
202
203 pub fn into_parts(self) -> (pin::Pin<&'app mut R>, life::Install<'owner, 'd>) {
204 (self.app, self.install)
205 }
206
207 pub fn into_install(self) -> life::Install<'owner, 'd> {
208 self.install
209 }
210}
211
212impl<'app, 'turn, 'driver, 'owner, 'd: 'owner, R> Shutdown<'app, 'turn, 'driver, 'owner, 'd, R> {
213 pub fn new(
214 app: pin::Pin<&'app mut R>,
215 turn: schedule::Turn<'turn, 'd>,
216 driver: retained::Context<'driver, 'owner, 'd>,
217 ) -> Self {
218 Self { app, turn, driver }
219 }
220
221 pub fn into_parts(
222 self,
223 ) -> (
224 pin::Pin<&'app mut R>,
225 schedule::Turn<'turn, 'd>,
226 retained::Context<'driver, 'owner, 'd>,
227 ) {
228 (self.app, self.turn, self.driver)
229 }
230
231 pub fn into_drive(
232 self,
233 ) -> (
234 schedule::Turn<'turn, 'd>,
235 retained::Context<'driver, 'owner, 'd>,
236 ) {
237 (self.turn, self.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 fn reborrow(&mut self) -> Drive<'_, '_, 'root, 'd> {
281 Drive {
282 turn: self.turn.reborrow(),
283 driver: self.driver.reborrow(),
284 }
285 }
286}
287
288const fn assert_layout() {
289 assert!(
290 mem::size_of::<Drive<'static, 'static, 'static, 'static>>() == 2 * mem::size_of::<usize>()
291 );
292 assert!(
293 mem::align_of::<Drive<'static, 'static, 'static, 'static>>() == mem::align_of::<usize>()
294 );
295 assert!(mem::size_of::<Install<'static, 'static, 'static, ()>>() == mem::size_of::<usize>());
296 assert!(
297 mem::size_of::<Shutdown<'static, 'static, 'static, 'static, 'static, ()>>()
298 == 3 * mem::size_of::<usize>()
299 );
300 assert!(
301 mem::size_of::<Finish<'static, 'static, 'static, 'static, 'static, ()>>()
302 == 2 * mem::size_of::<usize>()
303 );
304}
305
306const _: () = assert_layout();