103 lines
3.0 KiB
Rust
103 lines
3.0 KiB
Rust
use std::{
|
|
mem,
|
|
ops::DerefMut as _,
|
|
pin::Pin,
|
|
rc::Rc,
|
|
task::{Context, LocalWaker, Poll},
|
|
};
|
|
|
|
use io_uring::opcode::Nop;
|
|
use log::trace;
|
|
use unchecked_refcell::UncheckedRefCell;
|
|
|
|
use crate::{RT, Runtime, RuntimeInner, op::NoOp::Cancelled};
|
|
|
|
pub struct OpEntry(Rc<UncheckedRefCell<Op>>);
|
|
|
|
pub enum Op {
|
|
NoOp(NoOp),
|
|
}
|
|
|
|
enum NoOp {
|
|
New,
|
|
Live(LocalWaker),
|
|
Done,
|
|
Cancelled,
|
|
}
|
|
|
|
pub fn no_op() -> OpEntry {
|
|
OpEntry(Rc::new(UncheckedRefCell::new(Op::NoOp(NoOp::New))))
|
|
}
|
|
|
|
impl Future for OpEntry {
|
|
type Output = ();
|
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
let mut lock = self.0.borrow_mut();
|
|
match &mut *lock {
|
|
Op::NoOp(NoOp::Cancelled) => unreachable!(),
|
|
Op::NoOp(NoOp::Done) => Poll::Ready(()),
|
|
Op::NoOp(op @ NoOp::New) => {
|
|
{
|
|
let rt: &Runtime = cx.ext().downcast_ref().unwrap();
|
|
let mut lock = rt.0.borrow_mut();
|
|
let mut sq = lock.ring.submission();
|
|
let entry = Nop::new().build().user_data(
|
|
Rc::into_raw(self.0.clone())
|
|
.expose_provenance()
|
|
.try_into()
|
|
.unwrap(),
|
|
);
|
|
trace!("Pushing SQE {:?}", &entry);
|
|
unsafe { sq.push(&entry) }.expect("failed to submit no-op");
|
|
}
|
|
*op = NoOp::Live(cx.local_waker().clone());
|
|
Poll::Pending
|
|
}
|
|
Op::NoOp(NoOp::Live(waker)) => {
|
|
waker.clone_from(cx.local_waker());
|
|
Poll::Pending
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Op {
|
|
pub fn handle(this: Rc<UncheckedRefCell<Self>>) {
|
|
// TODO don't drop for multishot accepts
|
|
let mut lock = this.borrow_mut();
|
|
match lock.deref_mut() {
|
|
Op::NoOp(op) => match mem::replace(op, NoOp::Done) {
|
|
NoOp::New | NoOp::Done => unreachable!(),
|
|
NoOp::Cancelled => {}
|
|
NoOp::Live(waker) => waker.wake(),
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
impl Drop for OpEntry {
|
|
fn drop(&mut self) {
|
|
let mut lock = self.0.borrow_mut();
|
|
match lock.deref_mut() {
|
|
Op::NoOp(op) => {
|
|
match mem::replace(op, NoOp::Cancelled) {
|
|
NoOp::New | NoOp::Done => {}
|
|
NoOp::Cancelled => unreachable!(),
|
|
NoOp::Live(_) => {
|
|
RT.with(|rt| {
|
|
let outer = rt.borrow();
|
|
let mut lock = outer.as_ref().expect("future cancelled outside runtime thread").0.borrow_mut();
|
|
let mut sq = lock.ring.submission();
|
|
let entry = AsyncCancel::new(self.0.as_ptr().addr().try_into().unwrap()).build();
|
|
todo!()
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|