dope-uring 0.29.0

Owned io_uring backend for dope
Documentation
use std::{ops, task};

use dope_sys::{
    Budget,
    engine::{self, ring},
    io::reactor::ready::delivery,
    ring::ready::Complete as _,
};
use o3::mem::quota::Admission;

use crate::driver::{Engine, Turn, tuning::Progress};

enum Completion {}

impl<'a, C, H, Q: delivery::Quota<H>> engine::raw::Dispatch<'a, C, H, Q> for Turn<'a, H, Q>
where
    C: ring::Context + delivery::Context<H, Backend = Engine<C>>,
    C::Tuning: Progress<C::Token>,
{
    unsafe fn new(host: &'a mut H, quota: Q) -> Self {
        Self { host, quota }
    }

    fn dispatch(
        self,
        mut emit: impl FnMut(C::Event, &mut H) -> ops::ControlFlow<C::Event>,
    ) -> C::Dispatch {
        let Self { host, quota } = self;
        quota.reclaim(host);
        C::backend(host).ring.acquire();
        let result = {
            let limit = quota.remaining();
            let mut budget = quota.budget::<Completion>(limit);
            loop {
                let item = match budget.admit(|| C::resolve(host)) {
                    Admission::Item(item) => item,
                    Admission::Empty | Admission::Exhausted => break Ok(None),
                };
                let event = match item {
                    Ok(Some(event)) => event,
                    Ok(None) => continue,
                    Err(error) => break Err(error),
                };
                if let ops::ControlFlow::Break(event) = emit(event, host) {
                    break Ok(Some(event));
                }
            }
        };
        let pending = {
            let backend = C::backend(host);
            let complete = backend.ring.refresh();
            backend.ring.flush();
            complete.get() != 0 || backend.tuning.has_pending()
        };
        let state = if pending {
            task::Poll::Pending
        } else {
            task::Poll::Ready(())
        };
        match result {
            Err(error) => (task::Poll::Pending, error).into(),
            Ok(Some(event)) => (task::Poll::Pending, Some(event)).into(),
            Ok(None) => (state, None::<C::Event>).into(),
        }
    }
}