Skip to main content

dope_runtime/
runtime.rs

1use std::sync::Arc;
2use std::sync::atomic::{AtomicBool, Ordering};
3
4use dope_core::driver::{Backend, CompletionBackend, DriverLifecycle};
5
6pub type ManifoldDriver<M> = <<M as Manifold>::Backend as Backend>::Driver;
7
8pub trait Manifold {
9    type Backend: CompletionBackend;
10
11    fn has_pending(&self, _driver: &mut ManifoldDriver<Self>) -> bool {
12        false
13    }
14
15    fn drive(&mut self, driver: &mut ManifoldDriver<Self>);
16
17    fn park_timeout(&mut self) -> Option<std::time::Duration> {
18        None
19    }
20}
21
22pub struct Runtime<R: Manifold> {
23    pub(crate) reactor: R,
24    pub(crate) driver: ManifoldDriver<R>,
25    shutdown: Option<Arc<AtomicBool>>,
26}
27
28impl<R: Manifold> Runtime<R> {
29    pub fn new(reactor: R, driver: ManifoldDriver<R>) -> Self {
30        Self {
31            reactor,
32            driver,
33            shutdown: None,
34        }
35    }
36
37    pub fn with_shutdown(mut self, shutdown: Option<Arc<AtomicBool>>) -> Self {
38        self.shutdown = shutdown;
39        self
40    }
41
42    pub fn run_forever(mut self) -> std::io::Result<()> {
43        let Self {
44            reactor,
45            driver,
46            shutdown,
47        } = &mut self;
48
49        let driver_ptr: *mut ManifoldDriver<R> = &mut *driver;
50        R::Backend::set_current(driver_ptr);
51
52        loop {
53            if shutdown
54                .as_ref()
55                .is_some_and(|flag| flag.load(Ordering::Relaxed))
56            {
57                return Ok(());
58            }
59
60            reactor.drive(driver);
61
62            if reactor.has_pending(driver) {
63                let _ = driver.submit_only();
64            } else if let Some(timeout) = reactor.park_timeout() {
65                let _ = driver.park_for(timeout);
66            } else {
67                let _ = driver.park();
68            }
69        }
70    }
71}