use std::{
io,
task::{Context, Poll, Waker},
};
use crate::{driver::op::CompletionMeta, utils::slab::Ref};
pub(crate) enum Lifecycle {
Submitted,
Waiting(Waker),
#[allow(dead_code)]
Ignored(Box<dyn std::any::Any>),
Completed(io::Result<u32>, u32),
}
impl<'a> Ref<'a, Lifecycle> {
pub(crate) fn complete(mut self, result: io::Result<u32>, flags: u32) {
let ref_mut = &mut *self;
match ref_mut {
Lifecycle::Submitted => {
*ref_mut = Lifecycle::Completed(result, flags);
}
Lifecycle::Waiting(_) => {
let old = std::mem::replace(ref_mut, Lifecycle::Completed(result, flags));
match old {
Lifecycle::Waiting(waker) => {
waker.wake();
}
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
Lifecycle::Ignored(..) => {
self.remove();
}
Lifecycle::Completed(..) => unsafe { std::hint::unreachable_unchecked() },
}
}
#[allow(clippy::needless_pass_by_ref_mut)]
pub(crate) fn poll_op(mut self, cx: &mut Context<'_>) -> Poll<CompletionMeta> {
let ref_mut = &mut *self;
match ref_mut {
Lifecycle::Submitted => {
*ref_mut = Lifecycle::Waiting(cx.waker().clone());
return Poll::Pending;
}
Lifecycle::Waiting(waker) => {
if !waker.will_wake(cx.waker()) {
*ref_mut = Lifecycle::Waiting(cx.waker().clone());
}
return Poll::Pending;
}
_ => {}
}
match self.remove() {
Lifecycle::Completed(result, flags) => Poll::Ready(CompletionMeta { result, flags }),
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
pub(crate) fn drop_op<T: 'static>(mut self, data: &mut Option<T>) -> bool {
let ref_mut = &mut *self;
match ref_mut {
Lifecycle::Submitted | Lifecycle::Waiting(_) => {
if let Some(data) = data.take() {
*ref_mut = Lifecycle::Ignored(Box::new(data));
} else {
*ref_mut = Lifecycle::Ignored(Box::new(())); };
return false;
}
Lifecycle::Completed(..) => {
self.remove();
}
Lifecycle::Ignored(..) => unsafe { std::hint::unreachable_unchecked() },
}
true
}
}