#![deny(unsafe_code)]
use std::cell::UnsafeCell;
use std::marker::{PhantomData, PhantomPinned};
use std::pin::Pin;
use crate::wait_queue::{Entry, PinnedEntry, WaitQueue};
#[derive(Debug, Default)]
pub struct Pager<'s, S: SyncResult> {
wait_queue: UnsafeCell<WaitQueue>,
_phantom: PhantomData<&'s S>,
_pinned: PhantomPinned,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Error {
NotRegistered,
WrongMode,
NotReady,
}
pub trait SyncResult: Sized {
type Result: Clone + Copy + Eq + PartialEq;
fn to_result(value: u8, pager_error: Option<Error>) -> Self::Result;
}
impl<'s, S: SyncResult> Pager<'s, S> {
#[inline]
pub fn is_registered(self: &mut Pin<&mut Pager<'s, S>>) -> bool {
self.wait_queue().is_pollable()
}
#[inline]
pub async fn poll_async(self: &mut Pin<&mut Pager<'s, S>>) -> S::Result {
if !self.is_registered() {
return S::to_result(0, Some(Error::NotRegistered));
}
let wait_queue = self.wait_queue();
let pinned_entry = PinnedEntry(Pin::new(wait_queue.entry()));
let result = pinned_entry.await;
if result == Entry::ERROR_WRONG_MODE {
return S::to_result(result, Some(Error::WrongMode));
}
S::to_result(result, None)
}
#[inline]
pub fn poll_sync(self: &mut Pin<&mut Pager<'s, S>>) -> S::Result {
if !self.is_registered() {
return S::to_result(0, Some(Error::NotRegistered));
}
let result = self.wait_queue().entry().poll_result_sync();
if result == Entry::ERROR_WRONG_MODE {
return S::to_result(result, Some(Error::WrongMode));
}
S::to_result(result, None)
}
#[inline]
pub fn try_poll(self: &mut Pin<&mut Pager<'s, S>>) -> S::Result {
if !self.is_registered() {
return S::to_result(0, Some(Error::NotRegistered));
}
if let Some(result) = self.wait_queue().entry().try_consume_result() {
S::to_result(result, None)
} else {
S::to_result(0, Some(Error::NotReady))
}
}
#[inline]
pub(crate) fn wait_queue(&self) -> Pin<&WaitQueue> {
WaitQueue::pinned_wait_queue(self.wait_queue.get())
}
}