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}