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