use std::mem;
use dope_core::driver::{
self,
receive::Registration,
retained::flight,
route::{Identity, KeyTag},
schedule::ready,
};
use crate::{
link::{
egress::{self, data, reserve::demand},
pool::recv::storage::tail::Slot,
slot::{transmit::outcome, types},
},
wire,
};
#[must_use]
pub enum Decision<'d, ID: Identity> {
Ready,
Runnable(Resume<'d>),
External(outcome::Wait<'d, ID>),
Stale,
}
#[must_use = "close progress must schedule its exact ready owner"]
pub struct Resume<'d>(ready::Target<'d>);
impl<'d> Resume<'d> {
pub(in crate::link::pool::change) fn new<'w, ID: Identity + 'w, W: wire::Spec>(
slot: &types::Control<'w, 'd, ID, W>,
) -> Self {
Self(slot.io().wake_target())
}
pub(in crate::link::pool::change) fn from_target(target: ready::Target<'d>) -> Self {
Self(target)
}
pub fn reschedule(self) {
self.0.wake();
}
}
impl<'d, ID: Identity> Decision<'d, ID> {
pub fn runnable<'w, W: wire::Spec>(slot: &types::Control<'w, 'd, ID, W>) -> Self
where
ID: 'w,
{
Self::Runnable(Resume::new(slot))
}
}
pub enum Approval<S, R> {
Ready(R),
Pending(S),
Stale(S),
}
pub enum Kind {
Opening,
Connected,
}
pub(in crate::link::pool::change) enum Start<T> {
Ready(T),
Terminal,
}
impl<'a, 'w, 'd, ID: Identity + 'w, W, S, Q>
Start<Slot<'a, types::Connection<'w, 'd, ID, W, S>, ID, Q>>
where
'd: 'w,
W: wire::Spec + 'w + 'd,
{
pub(in crate::link::pool::change) fn begin(
mut entry: Slot<'a, types::Connection<'w, 'd, ID, W, S>, ID, Q>,
) -> Self {
entry.get_mut().engine.operations.lifecycle.close();
if entry.get().terminal.is_pending() {
return Self::Terminal;
}
let ready = entry.get().engine.ready_handle().target();
Registration::clear(ready);
entry.get_mut().engine.operations.recv.exhaustion().cancel();
Self::Ready(entry)
}
}
#[derive(Clone, Copy)]
pub enum Failure {
Receive(dope_core::Errno),
}
pub struct Io<
'a,
'p,
'w,
'd: 'w,
ID: Identity + 'w,
W: wire::Spec,
S,
B,
const IOV: usize,
D: demand::Mode,
> {
pub(in crate::link::pool::change) cause: Failure,
pub(in crate::link::pool::change) connection: &'a mut types::Connection<'w, 'd, ID, W, S>,
pub(in crate::link::pool::change) egress: &'a mut egress::Storage<'p, 'd, ID, B, IOV, D>,
}
impl<'a, 'p, 'w, 'd: 'w, ID: Identity + 'w, W: wire::Spec, S, B, const IOV: usize, D: demand::Mode>
Io<'a, 'p, 'w, 'd, ID, W, S, B, IOV, D>
{
pub fn failure(&self) -> Failure {
self.cause
}
pub fn connection(self) -> &'a mut types::Connection<'w, 'd, ID, W, S> {
self.connection
}
pub fn into_parts(
self,
) -> (
&'a mut types::Connection<'w, 'd, ID, W, S>,
egress::Queue<'a, 'p, 'd, IOV, B, D>,
)
where
B: data::raw::Payload<'d>,
{
let queue = self.egress.bind_queue(self.connection.key());
(self.connection, queue.reborrow())
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Phase {
Prepare,
Release,
}
const _: () = {
assert!(mem::size_of::<Phase>() == 1);
assert!(mem::size_of::<Failure>() == mem::size_of::<dope_core::Errno>());
let limit = mem::size_of::<(usize, usize, dope_core::Errno)>();
assert!(
mem::size_of::<
Io<
'static,
'static,
'static,
'static,
KeyTag<0>,
wire::Identity,
(),
(),
1,
demand::Fallible,
>,
>() <= limit
);
assert!(
mem::size_of::<
Option<
Io<
'static,
'static,
'static,
'static,
KeyTag<0>,
wire::Identity,
(),
(),
1,
demand::Fallible,
>,
>,
>() <= limit
);
};
pub type Owner<'ctx, 'claim, 'flights, 'slot, 'driver, 'runtime, 'w, 'd, ID, W, S, C, X> = (
&'ctx mut X,
&'claim C,
Phase,
&'flights flight::Slots<'d, ID>,
&'slot mut types::Connection<'w, 'd, ID, W, S>,
&'driver mut driver::Context<'runtime, 'd>,
);
pub type Commit<'ctx, 'claim, 'driver, 'runtime, 'd, C, X, S> = (
&'ctx mut X,
&'claim C,
S,
Kind,
&'driver mut driver::Context<'runtime, 'd>,
);
pub type Failed<
'ctx,
'claim,
'io,
'driver,
'runtime,
'p,
'w,
'd,
ID,
W,
S,
B,
const IOV: usize,
D,
C,
X,
> = (
&'ctx mut X,
&'claim C,
Io<'io, 'p, 'w, 'd, ID, W, S, B, IOV, D>,
&'driver mut driver::Context<'runtime, 'd>,
);
pub struct Handler<'a, C, X, O, K, F> {
pub claim: C,
pub context: &'a mut X,
pub owner: O,
pub commit: K,
pub failed: F,
}
pub enum Outcome<R, C> {
Retired(R),
Pending(C),
Stale(C),
Missing(C),
}