mod error;
mod step;
use std::{ops::ControlFlow, os::fd::BorrowedFd};
pub use error::Error;
pub use step::Step;
use crate::{engine, probe::Stopped};
pub(super) type Retirement<T, R> = Result<
T,
Stopped<
R,
Error<<<R as Resolver>::Backend as engine::raw::Poll>::Error, <R as Resolver>::Fault>,
>,
>;
pub trait Resolver: Sized {
type Backend: engine::raw::Poll;
type Fault: Copy;
fn backend(&mut self) -> &mut Self::Backend;
fn retire_one(&mut self) -> Step;
fn retire(&mut self) {
while let Step::Advanced = self.retire_one() {}
}
fn has_pending(&self) -> bool;
fn has_flights(&self) -> bool;
fn has_inflight(&self) -> bool;
}
pub trait Reclaim: Resolver {
fn reclaim(self) -> Result<ControlFlow<Self, Self>, Stopped<Self, Self::Fault>>;
fn fault(failure: Stopped<Self, Self::Fault>) -> Self;
fn reactor(&mut self, failure: <Self::Backend as engine::raw::Poll>::Error);
fn drain(mut self) -> Result<Self, Stopped<Self, Self::Fault>> {
let mut first = None;
let state = loop {
match self.reclaim() {
Ok(ControlFlow::Continue(state)) => self = state,
Ok(ControlFlow::Break(state)) => break state,
Err(failure) => {
first.get_or_insert(failure.cause);
self = Self::fault(failure);
}
}
};
match first {
None => Ok(state),
Some(cause) => Err(Stopped { state, cause }),
}
}
}
pub trait Terminal {
fn has_flights(&self) -> bool;
fn has_inflight(&self) -> bool;
fn has_pending(&self) -> bool;
fn source(&self) -> Option<BorrowedFd<'_>>;
}
pub trait Resume: Reclaim {
type Terminal<'s>: Terminal
where
Self: 's;
fn terminal(&mut self) -> (&mut Self::Backend, Self::Terminal<'_>);
}
pub trait Close: Resolver {
type Closing: Reclaim<Backend = Self::Backend, Fault = Self::Fault>;
fn into_closing(self) -> Self::Closing;
}
pub trait Cancel: Close {
type Cancelling: Reclaim<Backend = Self::Backend, Fault = Self::Fault>
+ Close<Closing = Self::Closing>;
fn cancel(self) -> Self::Cancelling;
}
pub trait Quiesced {
type Resolver: Reclaim;
fn into_inner(self) -> Self::Resolver;
}
pub trait Finish<'a, R>
where
R: Reclaim + 'a,
<R::Backend as engine::raw::Poll>::Context: 'a,
{
type Quiesced: Quiesced<Resolver = R>;
fn try_finish(resolver: R) -> Retirement<Self::Quiesced, R>;
}
pub trait Quiesce<'a, R>
where
R: Cancel + 'a,
<R::Backend as engine::raw::Poll>::Context: 'a,
{
type Quiesced: Quiesced<Resolver = R::Closing>;
fn try_quiesce(resolver: R) -> Retirement<Self::Quiesced, R::Closing>;
}