1use crate::{driver::life::finish, io::fd::handles};
2pub mod cancel;
3mod complete;
4pub(crate) mod raw;
5mod request;
6mod slots;
7pub mod storage;
8use std::{marker, mem};
9
10pub(crate) use complete::Complete;
11use dope_sys::{engine::admit::Cancelled, table::token::host};
12use o3::{alloc, base::marker::ThreadBound};
13pub(crate) use request::Request;
14use route::table;
15pub use slots::Slots;
16use table::conn;
17
18use crate::{
19 driver::{
20 self,
21 route::{self, kind},
22 },
23 io::fd::domain::retire,
24};
25
26type Invariant<'d> = (driver::Invariant<'d>, marker::PhantomData<ThreadBound>);
27
28const INDEX_BITS: u32 = route::SLOT_BITS;
29const GENERATION_BITS: u32 = 32;
30
31#[derive(Clone, Copy, Debug, Eq, PartialEq)]
32#[repr(C)]
33struct Target {
34 epoch: route::Epoch,
35 slot: [u8; 3],
36 auxiliary: [u8; 3],
37 kind: kind::Native,
38 route: route::Route,
39}
40
41impl Target {
42 fn new<Tag: route::Tag, C: kind::Flight>(target: route::Operation<'_, Tag, C>) -> Self {
43 let parts = target.parts();
44 Self {
45 epoch: parts.epoch(),
46 slot: parts.slot().into_le24(),
47 auxiliary: [0; 3],
48 kind: C::FLIGHT,
49 route: Tag::ROUTE,
50 }
51 }
52
53 fn token(self) -> route::Token {
54 let [a, b, c] = self.slot;
55 let [d, e, f] = self.auxiliary;
56 route::Token::from_flight(self.epoch, [a, b, c, d, e, f], self.kind, self.route)
57 }
58
59 fn bind<'d, C: kind::Class>(
60 self,
61 driver: driver::Invariant<'d>,
62 flight: raw::Echo,
63 ) -> route::Erased<'d, C> {
64 route::Erased {
65 token: self.token(),
66 flight: Some(flight),
67 driver,
68 class: marker::PhantomData,
69 }
70 }
71}
72
73#[repr(transparent)]
74pub(crate) struct Arena(storage::Flights<Target, INDEX_BITS, GENERATION_BITS>);
75
76#[derive(Clone, Copy, Eq, PartialEq)]
78#[repr(transparent)]
79pub struct Capacity(usize);
80
81pub struct Need<Tags, const GROUPS: usize = 1> {
83 caps: [Capacity; GROUPS],
84 tags: marker::PhantomData<Tags>,
85}
86
87#[derive(Clone, Copy, Eq, PartialEq, Debug)]
89pub enum ScaleError {
90 Product {
91 capacity: conn::Capacity,
92 factor: usize,
93 },
94 Limit {
95 actual: usize,
96 maximum: usize,
97 },
98}
99
100impl Capacity {
101 pub const fn fixed<const FLIGHTS: usize>() -> Self {
102 const { assert!(FLIGHTS > 0 && FLIGHTS <= route::SLOT_MASK as usize + 1) };
103 Self(FLIGHTS)
104 }
105
106 pub const fn table(capacity: table::Capacity) -> Self {
107 Self(capacity.count().get())
108 }
109
110 pub const fn connections<const PER_CONNECTION: usize>(
111 capacity: conn::Capacity,
112 ) -> Result<Self, ScaleError> {
113 const { assert!(PER_CONNECTION > 0) };
114 let Some(total) = (capacity.raw() as usize).checked_mul(PER_CONNECTION) else {
115 return Err(ScaleError::Product {
116 capacity,
117 factor: PER_CONNECTION,
118 });
119 };
120 let maximum = route::SLOT_MASK as usize + 1;
121 if total > maximum {
122 return Err(ScaleError::Limit {
123 actual: total,
124 maximum,
125 });
126 }
127 Ok(Self(total))
128 }
129
130 pub const fn capped<const MAX: usize>(capacity: table::Capacity) -> Self {
131 const { assert!(MAX > 0) };
132 let capacity = capacity.count().get();
133 Self(if capacity < MAX { capacity } else { MAX })
134 }
135
136 pub(crate) const fn get(self) -> usize {
137 self.0
138 }
139}
140
141impl<Tag: route::Tag> Need<Tag> {
142 pub const fn new(cap: Capacity) -> Self {
143 Self {
144 caps: [cap],
145 tags: marker::PhantomData,
146 }
147 }
148}
149
150impl<A: route::Tag> Need<A> {
151 pub fn pair<B: route::Tag>(self, other: Need<B>) -> Need<(A, B), 2> {
152 let Self {
153 caps: [first],
154 tags: marker::PhantomData,
155 } = self;
156 let Need {
157 caps: [second],
158 tags: marker::PhantomData,
159 } = other;
160 Need {
161 caps: [first, second],
162 tags: marker::PhantomData,
163 }
164 }
165}
166
167impl<A: route::Tag, B: route::Tag> Need<(A, B), 2> {
168 pub fn push<C: route::Tag>(self, other: Need<C>) -> Need<(A, B, C), 3> {
169 let Self {
170 caps: [first, second],
171 tags: marker::PhantomData,
172 } = self;
173 let Need {
174 caps: [third],
175 tags: marker::PhantomData,
176 } = other;
177 Need {
178 caps: [first, second, third],
179 tags: marker::PhantomData,
180 }
181 }
182}
183
184impl<Tags, const GROUPS: usize> Need<Tags, GROUPS> {
185 const fn into_caps(self) -> [Capacity; GROUPS] {
186 self.caps
187 }
188}
189
190#[must_use = "prepared flight slots must be committed"]
191pub struct Prepared<'a, 'd, Tags, const GROUPS: usize = 1> {
192 prepared: storage::Prepared<'a, 'd, Target, INDEX_BITS, GENERATION_BITS, GROUPS>,
193 driver: driver::Invariant<'d>,
194 tags: marker::PhantomData<Tags>,
195}
196
197#[must_use = "a validated flight vacancy must be reserved or released"]
198pub(crate) struct Vacant<'slot, 'd, Tag: route::Tag, C: kind::Class = <Tag as route::Tag>::Class> {
199 vacancy: storage::Vacant<'slot, 'd, Target, INDEX_BITS, GENERATION_BITS>,
200 target: Target,
201 driver: Invariant<'d>,
202 class: marker::PhantomData<(Tag, C)>,
203}
204
205#[must_use = "a reserved flight must be committed or released"]
206#[repr(transparent)]
207pub(crate) struct Reserved<'d, C: kind::Class = kind::Any> {
208 reservation: storage::Reserved<'d, Target, INDEX_BITS, GENERATION_BITS>,
209 driver: Invariant<'d>,
210 class: marker::PhantomData<C>,
211}
212
213#[must_use = "a live flight must reach terminal completion or quiescence"]
216#[repr(transparent)]
217pub struct Flight<'d, C: kind::Class = kind::Any> {
218 flight: storage::Lease<'d, Target, INDEX_BITS, GENERATION_BITS>,
219 driver: Invariant<'d>,
220 class: marker::PhantomData<C>,
221}
222
223pub(crate) struct Drain<'q, 'd> {
224 drain: storage::Drain<'q, Target, INDEX_BITS, GENERATION_BITS>,
225 driver: driver::Reference<'d>,
226}
227
228impl Arena {
229 pub(crate) fn new() -> Self {
230 Self(storage::Flights::new())
231 }
232
233 pub(in crate::driver) fn is_pending(&self) -> bool {
234 self.0.is_pending()
235 }
236
237 pub(in crate::driver) fn finish(&self) {
238 self.0.finish();
239 }
240
241 pub(crate) fn try_prepare<'a, 'd, Tags, const GROUPS: usize>(
242 &'a mut self,
243 need: Need<Tags, GROUPS>,
244 driver: driver::Reference<'d>,
245 ) -> Result<Prepared<'a, 'd, Tags, GROUPS>, alloc::Error> {
246 let access = raw::Access::new(&mut self.0, driver);
247 let (prepared, driver) = access.try_batch(need.into_caps().map(Capacity::get))?;
248 Ok(Prepared {
249 prepared,
250 driver,
251 tags: marker::PhantomData,
252 })
253 }
254}
255
256impl<'d, Tags, const GROUPS: usize> Prepared<'_, 'd, Tags, GROUPS> {
257 fn commit(
258 self,
259 ) -> (
260 [storage::Slots<'d, Target, INDEX_BITS, GENERATION_BITS>; GROUPS],
261 Invariant<'d>,
262 ) {
263 let Self {
264 prepared,
265 driver,
266 tags: marker::PhantomData,
267 } = self;
268 let slots = prepared.groups();
269 (slots, (driver, marker::PhantomData))
270 }
271}
272
273impl<'d, Tag: route::Tag> Prepared<'_, 'd, Tag> {
274 pub fn slots(self) -> Slots<'d, Tag> {
275 let ([slots], driver) = self.commit();
276 Slots::new(slots, driver)
277 }
278}
279
280impl<'d, A: route::Tag, B: route::Tag> Prepared<'_, 'd, (A, B), 2> {
281 pub fn slots(self) -> (Slots<'d, A>, Slots<'d, B>) {
282 let ([first, second], driver) = self.commit();
283 (Slots::new(first, driver), Slots::new(second, driver))
284 }
285}
286
287impl<'d, A: route::Tag, B: route::Tag, C: route::Tag> Prepared<'_, 'd, (A, B, C), 3> {
288 pub fn slots(self) -> (Slots<'d, A>, Slots<'d, B>, Slots<'d, C>) {
289 let ([first, second, third], driver) = self.commit();
290 (
291 Slots::new(first, driver),
292 Slots::new(second, driver),
293 Slots::new(third, driver),
294 )
295 }
296}
297
298impl<'d, Tag: route::Tag, C: kind::Class> Vacant<'_, 'd, Tag, C> {
299 pub(crate) fn reserve(self) -> Reserved<'d, C> {
300 Reserved {
301 reservation: self.vacancy.reserve(self.target),
302 driver: self.driver,
303 class: marker::PhantomData,
304 }
305 }
306}
307
308impl<'d, C: kind::Class> Reserved<'d, C> {
309 pub(crate) fn key(&self) -> raw::Echo {
310 raw::Echo::from_inner(self.reservation.echo())
311 }
312
313 pub(crate) fn commit(self) -> Flight<'d, C> {
314 Flight {
315 flight: self.reservation.commit(),
316 driver: self.driver,
317 class: marker::PhantomData,
318 }
319 }
320}
321
322impl<'q, 'd> Drain<'q, 'd> {
323 pub(crate) fn new(arena: &'q Arena, driver: driver::Reference<'d>) -> Self {
324 Self {
325 drain: arena.0.drain(),
326 driver,
327 }
328 }
329}
330
331impl<'q, 'd> host::Drain for Drain<'q, 'd> {
332 type Driver = driver::Reference<'d>;
333
334 fn driver(&self) -> Self::Driver {
335 self.driver
336 }
337
338 type Key = raw::Echo;
339 type Returned = retire::Returned;
340 type Flight = Complete<'q, 'd>;
341 type Echo = retire::Echo<'d>;
342 type Class = handles::Retirement;
343
344 fn bind(&self, key: raw::Echo) -> Option<Complete<'q, 'd>> {
345 self.drain.bind(key.into_inner()).map(|bound| Complete {
346 completion: bound,
347 driver: self.driver,
348 class: marker::PhantomData,
349 })
350 }
351
352 fn retired(&self, returned: Self::Returned) -> host::Closed<Self::Echo, Self::Class> {
353 use host::Closed;
354 match self.driver.descriptors().retirement().bind(returned) {
355 retire::Bind::Ready(echo) => Closed::Ready(echo),
356 retire::Bind::Class {
357 echo,
358 expected,
359 observed,
360 } => Closed::Class {
361 echo,
362 expected,
363 observed,
364 },
365 retire::Bind::Missing => Closed::Missing,
366 }
367 }
368}
369
370impl<'d, C: kind::Class> Flight<'d, C> {
371 pub(crate) fn is_pending(&self) -> bool {
372 self.flight.is_pending()
373 }
374
375 pub(crate) fn key(&self) -> raw::Echo {
376 raw::Echo::from_inner(self.flight.echo())
377 }
378
379 pub fn target(&self) -> route::Erased<'d, C> {
380 self.flight.value().bind(self.driver.0, self.key())
381 }
382
383 pub fn matches(&self, target: route::Erased<'d, C>) -> bool {
384 self.target().matches_flight(target)
385 }
386
387 pub(in crate::driver) fn finish(mut self, proof: &mut finish::Finish<'_, 'd>) {
388 self.driver.0 = proof.brand();
389 }
390}
391
392const _: () = {
393 assert!(mem::size_of::<Arena>() == 4 * mem::size_of::<usize>());
394 assert!(mem::align_of::<Arena>() == mem::align_of::<usize>());
395 assert!(mem::size_of::<Target>() == mem::size_of::<route::Token>());
396 assert!(mem::align_of::<Target>() == mem::align_of::<route::Token>());
397 assert!(mem::size_of::<raw::Echo>() == mem::size_of::<usize>());
398 assert!(mem::size_of::<Flight<'static>>() == mem::size_of::<usize>());
399 assert!(mem::size_of::<Option<Flight<'static>>>() == mem::size_of::<usize>());
400 assert!(mem::size_of::<Reserved<'static>>() == mem::size_of::<usize>());
401 assert!(
402 mem::size_of::<Vacant<'static, 'static, route::KeyTag<1>>>()
403 == mem::size_of::<storage::Vacant<'static, 'static, Target, INDEX_BITS, GENERATION_BITS>>(
404 ) + mem::size_of::<route::Token>()
405 );
406 assert!(mem::size_of::<Drain<'static, 'static>>() == 2 * mem::size_of::<usize>());
407 assert!(mem::size_of::<Complete<'static, 'static>>() == 2 * mem::size_of::<usize>());
408 assert!(mem::size_of::<Slots<'static, route::KeyTag<1>>>() == mem::size_of::<usize>());
409};
410
411pub(crate) struct Mismatch<'q, 'd> {
412 pub(crate) bound: Complete<'q, 'd>,
413 pub(crate) expected: kind::Native,
414 pub(crate) observed: kind::Native,
415}
416
417impl<'d, C: kind::Class> Flight<'d, C> {
418 pub fn try_cancel(
420 &mut self,
421 driver: &mut driver::Context<'_, 'd>,
422 ) -> Result<Cancelled, cancel::Error> {
423 driver.native().try_cancel(self)
424 }
425}
426
427impl<'d, C: kind::Class> Flight<'d, C> {
428 pub fn try_stop(
430 &mut self,
431 driver: &mut driver::Context<'_, 'd>,
432 ) -> Result<cancel::Outcome, cancel::Failure> {
433 let status = match self.try_cancel(driver) {
434 Ok(status) => status,
435 Err(cancel::Error::Full(_)) => {
436 return Ok(cancel::Outcome::Deferred);
437 }
438 Err(cancel::Error::Rejected(cause)) => return Err(cause),
439 };
440 Ok(match status {
441 Cancelled::Submitted => cancel::Outcome::Submitted,
442 Cancelled::Queued => cancel::Outcome::Queued,
443 Cancelled::Completed => cancel::Outcome::Completed,
444 })
445 }
446}