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