1use std::{fmt, mem, ops, process};
2
3use o3::{collections::batch::set, permit};
4
5use crate::{
6 backend::{self, fixed},
7 driver::{self, flight, route, schedule::ready},
8 io,
9};
10
11#[derive(Clone, Copy, Debug)]
12pub(crate) struct FixedSlot(route::SlotIndex, o3::ThreadBound);
13
14const _: () = assert!(mem::size_of::<FixedSlot>() == mem::size_of::<u32>());
15
16#[must_use = "accepted fixed-file authority must be delivered or reclaimed"]
17#[repr(transparent)]
18pub(crate) struct Accepted(FixedSlot);
19
20#[must_use = "created fixed-file authority must be delivered or reclaimed"]
21#[repr(transparent)]
22pub(crate) struct Created(FixedSlot);
23
24const _: () = assert!(mem::size_of::<Accepted>() == mem::size_of::<FixedSlot>());
25
26impl FixedSlot {
27 pub(crate) const fn from_index(index: route::SlotIndex) -> Self {
28 use o3::ThreadBound;
29 Self(index, ThreadBound::NEW)
30 }
31
32 pub(crate) fn raw(self) -> u32 {
33 self.0.raw()
34 }
35
36 pub(crate) fn token_index(self) -> route::SlotIndex {
37 self.0
38 }
39}
40
41impl set::DenseIndex for FixedSlot {
42 fn into_usize(self) -> usize {
43 self.raw() as usize
44 }
45
46 fn from_usize(raw: usize) -> Self {
47 Self::from_index(route::SlotIndex::from_bounded(raw as u32))
48 }
49}
50
51impl Accepted {
52 pub(crate) const fn from_live(slot: FixedSlot) -> Self {
53 Self(slot)
54 }
55
56 pub(crate) fn bind<'d>(self, driver: driver::Reference<'d>) -> Option<AcceptedSlot<'d>> {
57 let slot = self.0;
58 let Some(lease) = FixedLease::claim(slot, driver) else {
59 driver.maintenance().defer_descriptor(slot, None);
60 return None;
61 };
62 Some(AcceptedSlot { lease })
63 }
64
65 pub(crate) fn into_slot(self) -> FixedSlot {
66 self.0
67 }
68}
69
70impl Created {
71 pub(crate) const fn from_live(slot: FixedSlot) -> Self {
72 Self(slot)
73 }
74
75 pub(crate) fn bind<'d>(self, driver: driver::Reference<'d>) -> Option<CreatedSlot<'d>> {
76 match driver.outbound().complete_outbound_create_success(self.0) {
77 driver::CreateSuccess::Deliver(outbound) => Some(CreatedSlot {
78 driver,
79 slot: self.0,
80 outbound,
81 }),
82 driver::CreateSuccess::Close(close) => {
83 driver.maintenance().defer_close(close);
84 None
85 }
86 }
87 }
88}
89
90#[repr(transparent)]
91pub(crate) struct FixedLease<'d> {
92 lease: permit::Lease<FixedReturn<'d>>,
93}
94
95struct FixedReturn<'d> {
96 driver: driver::Reference<'d>,
97}
98
99struct FixedOwned {
100 slot: FixedSlot,
101 epoch: u32,
102}
103
104impl<'d> FixedReturn<'d> {
105 fn key(&self, owned: &FixedOwned) -> ready::FixedKey<'d> {
106 ready::FixedKey::new(owned.slot.raw(), owned.epoch)
107 }
108
109 fn release(&self, owned: FixedOwned) -> Option<ready::FixedRelease<'d>> {
110 self.driver.ready().release_fixed_ready(self.key(&owned))
111 }
112}
113
114impl permit::Return for FixedReturn<'_> {
115 type Item = FixedOwned;
116
117 fn return_item(&self, owned: Self::Item) {
118 if let Some(released) = self.release(owned) {
119 self.driver.maintenance().retire_fixed_release(released);
120 }
121 }
122}
123
124impl<'d> FixedLease<'d> {
125 fn new(driver: driver::Reference<'d>, slot: FixedSlot, epoch: u32) -> Self {
126 Self {
127 lease: permit::Lease::new(FixedReturn { driver }, FixedOwned { slot, epoch }),
128 }
129 }
130
131 fn claim(slot: FixedSlot, driver: driver::Reference<'d>) -> Option<Self> {
132 let key = driver.ready().claim_fixed_ready(slot)?;
133 Some(Self::new(driver, slot, key.epoch()))
134 }
135
136 fn from_reserved(slot: fixed::Slot<'d>, driver: driver::Reference<'d>) -> Option<Self> {
137 let fixed = slot.fixed();
138 let Some(key) = driver.ready().claim_fixed_ready(fixed) else {
139 driver.maintenance().defer_fixed_slot(slot.retire());
140 return None;
141 };
142 Some(Self::new(driver, slot.into_claimed(key), key.epoch()))
143 }
144
145 pub(crate) fn slot(&self) -> FixedSlot {
146 self.lease.item().slot
147 }
148
149 fn slot_ref(&self) -> &FixedSlot {
150 &self.lease.item().slot
151 }
152
153 fn key(&self) -> ready::FixedKey<'d> {
154 self.lease.sink().key(self.lease.item())
155 }
156
157 pub(super) fn driver(&self) -> driver::Reference<'d> {
158 self.lease.sink().driver
159 }
160
161 fn ready_handle(&self) -> ready::Handle<'d> {
162 self.driver().ready().fixed_ready(self.key())
163 }
164
165 fn release(self) -> ready::FixedRelease<'d> {
166 let (return_fixed, owned) = self.lease.into_parts();
167 let Some(released) = return_fixed.release(owned) else {
168 process::abort();
169 };
170 released
171 }
172}
173
174const _: () = {
175 assert!(
176 mem::size_of::<FixedLease<'static>>()
177 == mem::size_of::<(driver::Reference<'static>, FixedSlot, u32)>()
178 );
179 assert!(
180 mem::align_of::<FixedLease<'static>>()
181 == mem::align_of::<(driver::Reference<'static>, FixedSlot, u32)>()
182 );
183};
184
185#[repr(C)]
186pub struct AcceptedSlot<'d> {
187 lease: FixedLease<'d>,
188}
189
190#[must_use = "created socket must be activated or reclaimed"]
191#[repr(C)]
192pub struct CreatedSlot<'d> {
204 driver: driver::Reference<'d>,
205 slot: FixedSlot,
206 outbound: driver::OutboundKey,
207}
208
209const _: () =
210 assert!(mem::size_of::<AcceptedSlot<'static>>() == mem::size_of::<FixedLease<'static>>());
211const _: () =
212 assert!(mem::size_of::<CreatedSlot<'static>>() == mem::size_of::<Descriptor<'static>>());
213const _: () =
214 assert!(mem::size_of::<AcceptedSlot<'static>>() <= mem::size_of::<io::RecvEvent<'static>>());
215
216pub struct Descriptor<'d> {
217 lease: FixedLease<'d>,
218}
219
220#[repr(transparent)]
235pub struct DatagramDescriptor<'d>(Descriptor<'d>);
236
237pub struct SocketSlot<'d> {
239 lease: FixedLease<'d>,
240}
241
242pub struct CreatingSocket<'d> {
254 lease: FixedLease<'d>,
255 flight: flight::Flight<'d>,
256}
257
258const _: () =
259 assert!(mem::size_of::<Descriptor<'static>>() == mem::size_of::<FixedLease<'static>>());
260const _: () = {
261 assert!(mem::size_of::<DatagramDescriptor<'static>>() == mem::size_of::<Descriptor<'static>>());
262 assert!(
263 mem::align_of::<DatagramDescriptor<'static>>() == mem::align_of::<Descriptor<'static>>()
264 );
265};
266const _: () =
267 assert!(mem::size_of::<SocketSlot<'static>>() == mem::size_of::<Descriptor<'static>>());
268const _: () = assert!(
269 mem::size_of::<CreatingSocket<'static>>()
270 == mem::size_of::<(Descriptor<'static>, flight::Flight<'static>)>()
271);
272
273impl fmt::Debug for Descriptor<'_> {
274 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
275 formatter
276 .debug_tuple("Descriptor")
277 .field(&self.lease.slot().raw())
278 .finish()
279 }
280}
281
282impl fmt::Debug for DatagramDescriptor<'_> {
283 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
284 formatter
285 .debug_tuple("DatagramDescriptor")
286 .field(&self.index())
287 .finish()
288 }
289}
290
291impl<'d> DatagramDescriptor<'d> {
292 pub(crate) fn validated(descriptor: Descriptor<'d>) -> Self {
293 Self(descriptor)
294 }
295
296 pub fn into_descriptor(self) -> Descriptor<'d> {
297 self.0
298 }
299}
300
301impl<'d> From<DatagramDescriptor<'d>> for Descriptor<'d> {
302 fn from(descriptor: DatagramDescriptor<'d>) -> Self {
303 descriptor.into_descriptor()
304 }
305}
306
307impl<'d> ops::Deref for DatagramDescriptor<'d> {
308 type Target = Descriptor<'d>;
309
310 fn deref(&self) -> &Self::Target {
311 &self.0
312 }
313}
314
315impl fmt::Debug for SocketSlot<'_> {
316 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
317 formatter
318 .debug_tuple("SocketSlot")
319 .field(&self.lease.slot().raw())
320 .finish()
321 }
322}
323
324impl fmt::Debug for CreatingSocket<'_> {
325 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
326 formatter
327 .debug_tuple("CreatingSocket")
328 .field(&self.lease.slot().raw())
329 .finish()
330 }
331}
332
333impl<'d> AcceptedSlot<'d> {
334 pub fn bind(self) -> Descriptor<'d> {
335 let Self { lease } = self;
336 Descriptor { lease }
337 }
338}
339
340impl<'d> CreatedSlot<'d> {
341 fn matches(&self, lease: &FixedLease<'d>) -> bool {
342 self.driver.same_driver(lease.driver()) && self.slot.raw() == lease.slot().raw()
343 }
344
345 pub fn activate(
348 self,
349 socket: CreatingSocket<'d>,
350 ) -> Result<Descriptor<'d>, (CreatingSocket<'d>, Self)> {
351 if !self.matches(&socket.lease) {
352 return Err((socket, self));
353 }
354 let slot = socket.lease.slot();
355 if !socket
356 .lease
357 .driver()
358 .outbound()
359 .activate_outbound(self.outbound, slot)
360 {
361 return Err((socket, self));
362 }
363 let CreatingSocket { lease, flight } = socket;
364 let _created = mem::ManuallyDrop::new(self);
365 let _ = flight.complete();
366 Ok(Descriptor { lease })
367 }
368}
369
370impl<'d> Descriptor<'d> {
371 pub(crate) fn from_reserved_slot(
372 slot: fixed::Slot<'d>,
373 driver: driver::Reference<'d>,
374 ) -> Option<Self> {
375 Some(Self {
376 lease: FixedLease::from_reserved(slot, driver)?,
377 })
378 }
379
380 pub(crate) fn slot(&self) -> FixedSlot {
381 self.lease.slot()
382 }
383
384 pub(crate) fn slot_ref(&self) -> &FixedSlot {
385 self.lease.slot_ref()
386 }
387
388 pub fn index(&self) -> u32 {
389 self.lease.slot().raw()
390 }
391
392 pub fn token_index(&self) -> route::SlotIndex {
393 self.lease.slot().token_index()
394 }
395
396 pub fn driver(&self) -> driver::Reference<'d> {
397 self.lease.driver()
398 }
399
400 pub fn ready_handle(&self) -> ready::Handle<'d> {
401 self.lease.ready_handle()
402 }
403
404 pub(crate) fn into_lease(self) -> FixedLease<'d> {
405 let Self { lease } = self;
406 lease
407 }
408
409 pub(crate) fn close(self, backend: &mut backend::Backend) {
410 use fixed::Lifecycle;
411
412 let lease = self.into_lease();
413 let driver = lease.driver();
414 let released = lease.release();
415 let slot = released.slot();
416 match driver.files().fixed_owner(slot) {
417 driver::FixedOwner::Accepted => {
418 Lifecycle::close(
419 backend,
420 driver::Close::untracked(released.into_slot()),
421 driver,
422 fixed::Phase::Active,
423 );
424 }
425 driver::FixedOwner::Outbound(outbound) => {
426 match driver
427 .outbound()
428 .close_disposition(released.into_slot(), Some(outbound))
429 {
430 driver::CloseDisposition::Submit(close) => {
431 Lifecycle::close(backend, close, driver, fixed::Phase::Active);
432 }
433 driver::CloseDisposition::NoSubmit(Some(retired)) => {
434 let slots = driver.outbound().take_retired_slots(retired);
435 Lifecycle::release_slots(backend, slots);
436 }
437 driver::CloseDisposition::NoSubmit(None) => {}
438 }
439 }
440 driver::FixedOwner::Reserved => {
441 let retired = fixed::Retirement::from_release(released);
442 Lifecycle::retire(backend, retired.into_slot(), fixed::Phase::Active);
443 }
444 }
445 }
446}
447
448impl<'d> SocketSlot<'d> {
449 pub(crate) fn from_outbound_slot(
450 slot: FixedSlot,
451 driver: driver::Reference<'d>,
452 ) -> Option<Self> {
453 let Some(lease) = FixedLease::claim(slot, driver) else {
454 if let Some(slots) = driver.outbound().release_outbound_slot_for(slot) {
455 driver.maintenance().defer_outbound_slots(slots);
456 }
457 return None;
458 };
459 Some(Self { lease })
460 }
461
462 pub(crate) fn slot_ref(&self) -> &FixedSlot {
463 self.lease.slot_ref()
464 }
465
466 pub fn index(&self) -> u32 {
467 self.lease.slot().raw()
468 }
469
470 pub(crate) fn into_creating(self, flight: flight::Flight<'d>) -> CreatingSocket<'d> {
471 let slot = self.lease.slot();
472 if !self
473 .lease
474 .driver()
475 .outbound()
476 .begin_outbound_create_for(slot)
477 {
478 process::abort();
479 }
480 let lease = self.lease;
481 CreatingSocket { lease, flight }
482 }
483}
484
485impl<'d> CreatingSocket<'d> {
486 pub fn driver(&self) -> driver::Reference<'d> {
487 self.lease.driver()
488 }
489
490 pub fn ready_handle(&self) -> ready::Handle<'d> {
491 self.lease.ready_handle()
492 }
493}
494impl Drop for CreatedSlot<'_> {
495 fn drop(&mut self) {
496 self.driver
497 .maintenance()
498 .defer_descriptor(self.slot, Some(self.outbound));
499 }
500}