use std::pin;
use o3::mem::{Lease, Return, lease::Open};
use crate::driver::schedule::{
ready,
ready::{
task,
task::{pool, topology},
},
};
#[must_use = "a binding must be reclaimed or released"]
pub struct Binding<'node, 'd, I: topology::raw::Index> {
state: Lease<Restore<'node, 'd, I>, Open>,
}
struct Restore<'node, 'd, I: topology::raw::Index>(pin::Pin<&'node task::raw::Node<'d, I>>);
impl<'node, 'd, I: topology::raw::Index> Binding<'node, 'd, I> {
pub fn get(node: pin::Pin<&'node task::raw::Node<'d, I>>) -> Option<Self> {
let state = node.binding.take()?;
Some(Self {
state: Lease::open(Restore(node), state),
})
}
pub unsafe fn bind_leased<'lease>(
node: pin::Pin<&'node task::raw::Node<'d, I>>,
admit: task::raw::Lease<'lease, 'd>,
edge: topology::Edge<'node, 'd, I>,
) -> Self {
Self {
state: Lease::open(Restore(node), unsafe {
task::raw::State::bind(admit.take(), edge)
}),
}
}
pub fn waker(&self) -> task::Parent<'d> {
self.state().waker()
}
pub fn release(self) {
self.into_state().return_item(());
}
pub unsafe fn reclaim<Tag, const N: usize>(
self,
domain: &mut task::Domain<'d, Tag, N>,
) -> task::Reclaim {
let held = self.reclaim_task();
domain.reclaim(held)
}
pub unsafe fn reclaim_pool<Tag, const N: usize>(
self,
pool: &pool::Pool<'d, Tag, N>,
root: pool::Root<'d>,
) {
let held = self.reclaim_task();
pool.reclaim(root, held, (), ())
}
fn reclaim_task(self) -> ready::Reclaimed<'d> {
let state = self.into_state();
state.parent.reclaim_task(state.child)
}
fn into_state(self) -> task::raw::State<'d> {
self.state.into_parts().1
}
fn state(&self) -> &task::raw::State<'d> {
self.state.item()
}
pub fn unbind(node: pin::Pin<&'node task::raw::Node<'d, I>>) {
if let Some(binding) = Self::get(node) {
binding.release();
}
}
}
impl<'d, I: topology::raw::Index> Return for Restore<'_, 'd, I> {
type Item = task::raw::State<'d>;
fn return_item(self, state: Self::Item) {
self.0.binding.set(Some(state));
}
}