use crate::{config, engine::retry, sys};
use dope_core::driver::schedule::{clock, ready::wake};
use o3::mem::{self, lease};
use std::{marker, task};
pub(crate) trait Role {
const FINISH: bool;
fn limits(config: &config::Config) -> &config::Contention;
}
pub(crate) enum Open {}
pub(crate) enum Call {}
pub(crate) struct Lease<'slot, 'd, R: Role> {
slot: mem::Lease<Return<'slot, 'd, R>, lease::Open>,
}
struct Return<'slot, 'd, R>(marker::PhantomData<(retry::raw::Loan<'slot, 'd>, R)>);
impl<'slot, 'd, R: Role> Lease<'slot, 'd, R> {
pub(super) const fn new(slot: retry::raw::Loan<'slot, 'd>) -> Self {
Self {
slot: mem::Lease::open(Return(marker::PhantomData), slot),
}
}
pub(crate) fn config(&self) -> &'slot config::Config {
self.slot.item().config()
}
pub(crate) fn defer(
&mut self,
now: clock::Moment<'d>,
fault: sys::Fault,
wake: wake::Waker<'d>,
) -> task::Poll<Result<(), crate::Error>> {
let limits = R::limits(self.config());
self.slot
.item_mut()
.slot_mut()
.defer(limits, now, fault, wake)
}
pub(crate) fn wait(&self) -> retry::Wait {
self.slot.item().slot().wait()
}
pub(crate) fn poll(
&mut self,
now: clock::Moment<'d>,
wake: wake::Waker<'d>,
) -> task::Poll<Result<(), crate::Error>> {
self.slot.item_mut().slot_mut().poll(now, wake)
}
}
impl<'slot, 'd, R: Role> mem::Return for Return<'slot, 'd, R> {
type Item = retry::raw::Loan<'slot, 'd>;
fn return_item(self, mut slot: Self::Item) {
if R::FINISH {
slot.finish();
}
}
}
impl Role for Open {
const FINISH: bool = false;
fn limits(config: &config::Config) -> &config::Contention {
&config.work.open.contention
}
}
impl Role for Call {
const FINISH: bool = true;
fn limits(config: &config::Config) -> &config::Contention {
&config.work.call.contention
}
}
const _: () = {
let word = size_of::<usize>();
assert!(size_of::<Lease<'static, 'static, Open>>() == word);
assert!(size_of::<Lease<'static, 'static, Call>>() == word);
};