dope-runtime 0.2.3

Thin io_uring adaptor with "Manifolds"
Documentation
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use dope_core::driver::{Backend, CompletionBackend, DriverLifecycle};

pub type ManifoldDriver<M> = <<M as Manifold>::Backend as Backend>::Driver;

pub trait Manifold {
    type Backend: CompletionBackend;

    fn has_pending(&self, _driver: &mut ManifoldDriver<Self>) -> bool {
        false
    }

    fn drive(&mut self, driver: &mut ManifoldDriver<Self>);

    fn park_timeout(&mut self) -> Option<std::time::Duration> {
        None
    }
}

pub struct Runtime<R: Manifold> {
    pub(crate) reactor: R,
    pub(crate) driver: ManifoldDriver<R>,
    shutdown: Option<Arc<AtomicBool>>,
}

impl<R: Manifold> Runtime<R> {
    pub fn new(reactor: R, driver: ManifoldDriver<R>) -> Self {
        Self {
            reactor,
            driver,
            shutdown: None,
        }
    }

    pub fn with_shutdown(mut self, shutdown: Option<Arc<AtomicBool>>) -> Self {
        self.shutdown = shutdown;
        self
    }

    pub fn run_forever(mut self) -> std::io::Result<()> {
        let Self {
            reactor,
            driver,
            shutdown,
        } = &mut self;

        let driver_ptr: *mut ManifoldDriver<R> = &mut *driver;
        R::Backend::set_current(driver_ptr);

        loop {
            if shutdown
                .as_ref()
                .is_some_and(|flag| flag.load(Ordering::Relaxed))
            {
                return Ok(());
            }

            reactor.drive(driver);

            if reactor.has_pending(driver) {
                let _ = driver.submit_only();
            } else if let Some(timeout) = reactor.park_timeout() {
                let _ = driver.park_for(timeout);
            } else {
                let _ = driver.park();
            }
        }
    }
}