use std::marker;
use dope_core::driver::{
receive::credit,
route::{Identity, KeyTag, table::conn},
};
use o3::depot::queue::tagged::entry;
use receive::mode;
use crate::wire::{self, receive, terminal};
mod borrowed;
mod direct;
pub use borrowed::Borrowed;
pub use direct::Direct;
pub trait Wait<'d, ID: Identity, W: wire::Spec> {
type Registration: Registration;
fn register(
self,
credit: credit::Pending<'d, ID>,
) -> Result<Self::Registration, entry::Error<conn::Capacity>>;
}
pub trait Registration {
fn commit(self);
}
pub trait Completion {
fn complete(self);
}
pub(crate) trait Immediate<W: wire::Spec>: Kind<W, Wait = mode::Disabled> {
fn reserve<'a, 'w, 'd, ID: Identity + 'w>(
wire: &'a mut W::Connection<'w, ID>,
run: &'a mut W::Runtime<'w, 'd, ID>,
) -> Self::Transaction<'a, 'w, 'd, ID>
where
W: 'w,
'd: 'w,
'w: 'a;
}
pub trait Kind<W: wire::Spec> {
type Wait: mode::Flag;
type Transaction<'a, 'w, 'd, ID: Identity + 'w>
where
W: 'w,
'd: 'w,
'w: 'a;
}
#[must_use]
pub enum Outcome<T, B, E> {
Ready(T),
Blocked(B),
Failed(E),
}
pub trait Try<W: wire::Spec> {
type Block<'a, 'w, 'd, ID: Identity + 'w>: Wait<'d, ID, W>
where
W: 'w,
'd: 'w,
'w: 'a;
type Transaction<'a, 'w, 'd, ID: Identity + 'w>: Completion
where
W: 'w,
'd: 'w,
'w: 'a;
fn try_reserve<'a, 'w, 'd, ID: Identity + 'w>(
wire: &'a mut W::Connection<'w, ID>,
send: Option<&'a mut W::SendStorage<'w>>,
run: &'a mut W::Runtime<'w, 'd, ID>,
) -> Outcome<
Self::Transaction<'a, 'w, 'd, ID>,
Self::Block<'a, 'w, 'd, ID>,
terminal::Error<'w, W>,
>
where
W: 'w,
'd: 'w,
'w: 'a;
fn cancel<'w, 'd, ID: Identity + 'w>(
run: &mut W::Runtime<'w, 'd, ID>,
target: credit::Id<'d, ID>,
) where
W: 'w,
'd: 'w;
fn release_recv<'w, 'd, ID: Identity + 'w>(run: &mut W::Runtime<'w, 'd, ID>)
where
W: 'w,
'd: 'w;
fn release_send<'w, 'd, ID: Identity + 'w>(run: &mut W::Runtime<'w, 'd, ID>)
where
W: 'w,
'd: 'w;
}
pub struct Waiting<P>(marker::PhantomData<fn() -> P>);
impl<W, P> Kind<W> for Waiting<P>
where
W: wire::Spec,
P: Try<W>,
{
type Wait = mode::Waiting<P>;
type Transaction<'a, 'w, 'd, ID: Identity + 'w>
= P::Transaction<'a, 'w, 'd, ID>
where
W: 'w,
'd: 'w,
'w: 'a;
}
pub struct Guard<ID: Identity, W>(marker::PhantomData<fn() -> (W, ID)>);
impl<ID: Identity, W> Completion for Guard<ID, W> {
fn complete(self) {
let Self(marker::PhantomData) = self;
}
}
#[repr(transparent)]
pub struct Transaction<'a, 'w, ID: Identity + 'w, W>
where
W: wire::Spec + 'w,
'w: 'a,
{
wire: &'a mut W::Connection<'w, ID>,
}
impl<'a, 'w, ID: Identity + 'w, W> Transaction<'a, 'w, ID, W>
where
W: wire::Spec + 'w,
'w: 'a,
{
pub fn into_wire(self) -> &'a mut W::Connection<'w, ID> {
self.wire
}
}
const _: () = assert!(size_of::<Guard<KeyTag<0>, wire::Identity>>() == 0);
const _: () = assert!(
size_of::<Transaction<'static, 'static, KeyTag<0>, wire::Identity>>()
== size_of::<&mut wire::Identity>()
);