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
39pub enum PollResult {
40    Ready,
41    Pending,
42    PollAgain,
43}
44
45pub trait Notify: Send + Sync + fmt::Debug + 'static {
46    fn notify(&self) -> io::Result<()>;
47}
48
49#[cfg(windows)]
50#[macro_export]
51macro_rules! syscall {
52    (BOOL, $e:expr) => {
53        $crate::syscall!($e, == 0)
54    };
55    (SOCKET, $e:expr) => {
56        $crate::syscall!($e, != 0)
57    };
58    (HANDLE, $e:expr) => {
59        $crate::syscall!($e, == ::windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE)
60    };
61    ($e:expr, $op: tt $rhs: expr) => {{
62        #[allow(unused_unsafe)]
63        let res = unsafe { $e };
64        if res $op $rhs {
65            Err(::std::io::Error::last_os_error())
66        } else {
67            Ok(res)
68        }
69    }};
70}
71
72/// Helper macro to execute a system call
73#[cfg(unix)]
74#[macro_export]
75macro_rules! syscall {
76    (break $e:expr) => {
77        loop {
78            match $crate::syscall!($e) {
79                Ok(fd) => break ::std::task::Poll::Ready(Ok(fd as usize)),
80                Err(e) if e.kind() == ::std::io::ErrorKind::WouldBlock || e.raw_os_error() == Some(::libc::EINPROGRESS)
81                    => break ::std::task::Poll::Pending,
82                Err(e) if e.kind() == ::std::io::ErrorKind::Interrupted => {},
83                Err(e) => break ::std::task::Poll::Ready(Err(e)),
84            }
85        }
86    };
87    ($e:expr, $f:ident($fd:expr)) => {
88        match $crate::syscall!(break $e) {
89            ::std::task::Poll::Pending => Ok($crate::sys::Decision::$f($fd)),
90            ::std::task::Poll::Ready(Ok(res)) => Ok($crate::sys::Decision::Completed(res)),
91            ::std::task::Poll::Ready(Err(e)) => Err(e),
92        }
93    };
94    ($e:expr) => {{
95        #[allow(unused_unsafe)]
96        let res = unsafe { $e };
97        if res == -1 {
98            Err(::std::io::Error::last_os_error())
99        } else {
100            Ok(res)
101        }
102    }};
103}