//! Abstracts out the entire chain of runtime sub-drivers into common types. use crate::park::thread::ParkThread; use crate::park::Park; use std::io; use std::time::Duration; // ===== io driver ===== cfg_io_driver! { type IoDriver = crate::io::driver::Driver; type IoStack = crate::park::either::Either; pub(crate) type IoHandle = Option; fn create_io_stack(enabled: bool) -> io::Result<(IoStack, IoHandle, SignalHandle)> { use crate::park::either::Either; #[cfg(loom)] assert!(!enabled); let ret = if enabled { let io_driver = crate::io::driver::Driver::new()?; let io_handle = io_driver.handle(); let (signal_driver, signal_handle) = create_signal_driver(io_driver)?; let process_driver = create_process_driver(signal_driver)?; (Either::A(process_driver), Some(io_handle), signal_handle) } else { (Either::B(ParkThread::new()), Default::default(), Default::default()) }; Ok(ret) } } cfg_not_io_driver! { pub(crate) type IoHandle = (); type IoStack = ParkThread; fn create_io_stack(_enabled: bool) -> io::Result<(IoStack, IoHandle, SignalHandle)> { Ok((ParkThread::new(), Default::default(), Default::default())) } } // ===== signal driver ===== macro_rules! cfg_signal_internal_and_unix { ($($item:item)*) => { #[cfg(unix)] cfg_signal_internal! { $($item)* } } } cfg_signal_internal_and_unix! { type SignalDriver = crate::signal::unix::driver::Driver; pub(crate) type SignalHandle = Option; fn create_signal_driver(io_driver: IoDriver) -> io::Result<(SignalDriver, SignalHandle)> { let driver = crate::signal::unix::driver::Driver::new(io_driver)?; let handle = driver.handle(); Ok((driver, Some(handle))) } } cfg_not_signal_internal! { pub(crate) type SignalHandle = (); cfg_io_driver! { type SignalDriver = IoDriver; fn create_signal_driver(io_driver: IoDriver) -> io::Result<(SignalDriver, SignalHandle)> { Ok((io_driver, ())) } } } // ===== process driver ===== cfg_process_driver! { type ProcessDriver = crate::process::unix::driver::Driver; fn create_process_driver(signal_driver: SignalDriver) -> io::Result { crate::process::unix::driver::Driver::new(signal_driver) } } cfg_not_process_driver! { cfg_io_driver! { type ProcessDriver = SignalDriver; fn create_process_driver(signal_driver: SignalDriver) -> io::Result { Ok(signal_driver) } } } // ===== time driver ===== cfg_time! { type TimeDriver = crate::park::either::Either, IoStack>; pub(crate) type Clock = crate::time::Clock; pub(crate) type TimeHandle = Option; fn create_clock() -> Clock { crate::time::Clock::new() } fn create_time_driver( enable: bool, io_stack: IoStack, clock: Clock, ) -> (TimeDriver, TimeHandle) { use crate::park::either::Either; if enable { let driver = crate::time::driver::Driver::new(io_stack, clock); let handle = driver.handle(); (Either::A(driver), Some(handle)) } else { (Either::B(io_stack), None) } } } cfg_not_time! { type TimeDriver = IoStack; pub(crate) type Clock = (); pub(crate) type TimeHandle = (); fn create_clock() -> Clock { () } fn create_time_driver( _enable: bool, io_stack: IoStack, _clock: Clock, ) -> (TimeDriver, TimeHandle) { (io_stack, ()) } } // ===== runtime driver ===== #[derive(Debug)] pub(crate) struct Driver { inner: TimeDriver, } pub(crate) struct Resources { pub(crate) io_handle: IoHandle, pub(crate) signal_handle: SignalHandle, pub(crate) time_handle: TimeHandle, pub(crate) clock: Clock, } pub(crate) struct Cfg { pub(crate) enable_io: bool, pub(crate) enable_time: bool, } impl Driver { pub(crate) fn new(cfg: Cfg) -> io::Result<(Self, Resources)> { let (io_stack, io_handle, signal_handle) = create_io_stack(cfg.enable_io)?; let clock = create_clock(); let (time_driver, time_handle) = create_time_driver(cfg.enable_time, io_stack, clock.clone()); Ok(( Self { inner: time_driver }, Resources { io_handle, signal_handle, time_handle, clock, }, )) } } impl Park for Driver { type Unpark = ::Unpark; type Error = ::Error; fn unpark(&self) -> Self::Unpark { self.inner.unpark() } fn park(&mut self) -> Result<(), Self::Error> { self.inner.park() } fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error> { self.inner.park_timeout(duration) } fn shutdown(&mut self) { self.inner.shutdown() } }