use dope_core::driver::{self, route::table::conn, settings};
use o3::{
depot,
depot::{index::Initialized, queue::pool},
};
use crate::{
link::{
event,
pool::recv::storage::{self, Extent, queue},
},
wire::receive::mode::{Disabled, Enabled, Parking, Waiting},
};
pub unsafe trait Mode {
type Storage<'d, R>;
type Bound<'a, 'd: 'a, R: 'a>: queue::Ops<'d, R>;
fn try_storage<'d, R>(
cap: conn::Capacity,
bufs: settings::Buffers,
driver: driver::Reference<'d>,
) -> crate::Result<Self::Storage<'d, R>>;
fn extent<'d, R>(storage: &Self::Storage<'d, R>) -> Extent;
fn has_queued<'d, R>(
slot: depot::raw::Proof<(&Self::Storage<'d, R>, usize), Initialized<()>>,
) -> bool;
fn bind<'a, 'd: 'a, R: 'a>(
slot: depot::raw::Proof<(&'a mut Self::Storage<'d, R>, usize), Initialized<()>>,
) -> Self::Bound<'a, 'd, R>;
}
unsafe impl storage::raw::Mode for Disabled {
type Storage<'d, R> = ();
type Bound<'a, 'd: 'a, R: 'a> = &'a mut ();
fn try_storage<'d, R>(
_: conn::Capacity,
_: settings::Buffers,
_: driver::Reference<'d>,
) -> crate::Result<()> {
Ok(())
}
fn extent<'d, R>((): &()) -> Extent {
Extent::Empty
}
fn has_queued<'d, R>(_: depot::raw::Proof<(&(), usize), Initialized<()>>) -> bool {
false
}
fn bind<'a, 'd: 'a, R: 'a>(
slot: depot::raw::Proof<(&'a mut (), usize), Initialized<()>>,
) -> Self::Bound<'a, 'd, R> {
slot.into_inner().0
}
}
unsafe impl storage::raw::Mode for Parking {
type Storage<'d, R> = storage::Parking<'d, R>;
type Bound<'a, 'd: 'a, R: 'a> = pool::Lane<'a, event::Completion<'d, R>>;
fn try_storage<'d, R>(
cap: conn::Capacity,
bufs: settings::Buffers,
_: driver::Reference<'d>,
) -> crate::Result<storage::Parking<'d, R>> {
storage::Parking::try_new(cap, bufs)
}
fn extent<'d, R>(storage: &Self::Storage<'d, R>) -> Extent {
Extent::Lanes(storage.events.len())
}
fn has_queued<'d, R>(
slot: depot::raw::Proof<(&Self::Storage<'d, R>, usize), Initialized<()>>,
) -> bool {
let (storage, index) = slot.into_inner();
unsafe { has_queued(&storage.events, index) }
}
fn bind<'a, 'd: 'a, R: 'a>(
slot: depot::raw::Proof<(&'a mut Self::Storage<'d, R>, usize), Initialized<()>>,
) -> Self::Bound<'a, 'd, R> {
let (storage, index) = slot.into_inner();
use o3::depot::raw::Proof;
unsafe { Proof::new((&mut storage.events, index)) }.into()
}
}
unsafe impl storage::raw::Mode for Enabled {
type Storage<'d, R> = storage::Retained<'d, R>;
type Bound<'a, 'd: 'a, R: 'a> = storage::Loan<'a, 'd, R>;
fn try_storage<'d, R>(
cap: conn::Capacity,
bufs: settings::Buffers,
driver: driver::Reference<'d>,
) -> crate::Result<storage::Retained<'d, R>> {
retained(cap, bufs, driver)
}
fn extent<'d, R>(storage: &Self::Storage<'d, R>) -> Extent {
Extent::Lanes(storage.events.events.len())
}
fn has_queued<'d, R>(
slot: depot::raw::Proof<(&Self::Storage<'d, R>, usize), Initialized<()>>,
) -> bool {
let (storage, index) = slot.into_inner();
unsafe { has_queued(&storage.events.events, index) }
}
fn bind<'a, 'd: 'a, R: 'a>(
slot: depot::raw::Proof<(&'a mut Self::Storage<'d, R>, usize), Initialized<()>>,
) -> Self::Bound<'a, 'd, R> {
let (storage, index) = slot.into_inner();
unsafe { bind_retained(storage, index) }
}
}
unsafe impl<Q> storage::raw::Mode for Waiting<Q> {
type Storage<'d, R> = storage::Retained<'d, R>;
type Bound<'a, 'd: 'a, R: 'a> = storage::Loan<'a, 'd, R>;
fn try_storage<'d, R>(
cap: conn::Capacity,
bufs: settings::Buffers,
driver: driver::Reference<'d>,
) -> crate::Result<storage::Retained<'d, R>> {
<Enabled as storage::raw::Mode>::try_storage(cap, bufs, driver)
}
fn extent<'d, R>(storage: &Self::Storage<'d, R>) -> Extent {
<Enabled as storage::raw::Mode>::extent(storage)
}
fn has_queued<'d, R>(
slot: depot::raw::Proof<(&Self::Storage<'d, R>, usize), Initialized<()>>,
) -> bool {
<Enabled as storage::raw::Mode>::has_queued(slot)
}
fn bind<'a, 'd: 'a, R: 'a>(
slot: depot::raw::Proof<(&'a mut Self::Storage<'d, R>, usize), Initialized<()>>,
) -> Self::Bound<'a, 'd, R> {
<Enabled as storage::raw::Mode>::bind(slot)
}
}
fn retained<'d, R>(
cap: conn::Capacity,
bufs: settings::Buffers,
driver: driver::Reference<'d>,
) -> crate::Result<storage::Retained<'d, R>> {
let credit = driver
.scheduler()
.try_storage(cap)
.map_err(crate::Resource::Credit)?;
storage::Retained::try_new(cap, bufs, credit)
}
unsafe fn has_queued<R>(events: &pool::Lanes<event::Completion<'_, R>>, index: usize) -> bool {
use o3::depot::raw::Proof;
!unsafe { Proof::new((events, index)) }.into().is_empty()
}
unsafe fn bind_retained<'a, 'd: 'a, R>(
storage: &'a mut storage::Retained<'d, R>,
index: usize,
) -> storage::Loan<'a, 'd, R> {
use o3::depot::raw::Proof;
let events = unsafe { Proof::new((&mut storage.events.events, index)) }.into();
let credit = unsafe { Proof::new((&storage.credit, index)) }.into();
storage::Loan::new(events, credit)
}