Skip to main content

ntex_rt/
driver.rs

1//! The platform-specified driver.
2use std::{fmt, io, pin::Pin};
3
4use crate::rt::Runtime;
5
6pub type BlockFuture = Pin<Box<dyn Future<Output = ()> + 'static>>;
7
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9pub enum DriverType {
10    Poll,
11    IoUring,
12}
13
14impl DriverType {
15    pub const fn name(&self) -> &'static str {
16        match self {
17            DriverType::Poll => "polling",
18            DriverType::IoUring => "io-uring",
19        }
20    }
21
22    pub const fn is_polling(&self) -> bool {
23        matches!(self, &DriverType::Poll)
24    }
25}
26
27pub trait Runner: Send + Sync + 'static {
28    fn block_on(&self, fut: BlockFuture);
29}
30
31pub trait Driver: 'static {
32    fn handle(&self) -> Box<dyn Notify>;
33
34    fn run(&self, rt: &Runtime) -> io::Result<()>;
35
36    fn clear(&self);
37}
38
39#[derive(Copy, Clone, Debug, PartialEq, Eq)]
40pub enum PollResult {
41    Ready,
42    Pending,
43    PollAgain,
44}
45
46pub trait Notify: Send + Sync + fmt::Debug + 'static {
47    fn notify(&self) -> io::Result<()>;
48}
49
50#[cfg(windows)]
51#[macro_export]
52macro_rules! syscall {
53    (BOOL, $e:expr) => {
54        $crate::syscall!($e, == 0)
55    };
56    (SOCKET, $e:expr) => {
57        $crate::syscall!($e, != 0)
58    };
59    (HANDLE, $e:expr) => {
60        $crate::syscall!($e, == ::windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE)
61    };
62    ($e:expr, $op: tt $rhs: expr) => {{
63        #[allow(unused_unsafe)]
64        let res = unsafe { $e };
65        if res $op $rhs {
66            Err(::std::io::Error::last_os_error())
67        } else {
68            Ok(res)
69        }
70    }};
71}
72
73/// Helper macro to execute a system call
74#[cfg(unix)]
75#[macro_export]
76macro_rules! syscall {
77    (break $e:expr) => {
78        loop {
79            match $crate::syscall!($e) {
80                Ok(fd) => break ::std::task::Poll::Ready(Ok(fd as usize)),
81                Err(e) if e.kind() == ::std::io::ErrorKind::WouldBlock || e.raw_os_error() == Some(::libc::EINPROGRESS)
82                    => break ::std::task::Poll::Pending,
83                Err(e) if e.kind() == ::std::io::ErrorKind::Interrupted => {},
84                Err(e) => break ::std::task::Poll::Ready(Err(e)),
85            }
86        }
87    };
88    ($e:expr, $f:ident($fd:expr)) => {
89        match $crate::syscall!(break $e) {
90            ::std::task::Poll::Pending => Ok($crate::sys::Decision::$f($fd)),
91            ::std::task::Poll::Ready(Ok(res)) => Ok($crate::sys::Decision::Completed(res)),
92            ::std::task::Poll::Ready(Err(e)) => Err(e),
93        }
94    };
95    ($e:expr) => {{
96        #[allow(unused_unsafe)]
97        let res = unsafe { $e };
98        if res == -1 {
99            Err(::std::io::Error::last_os_error())
100        } else {
101            Ok(res)
102        }
103    }};
104}