1use std::{any::Any, cell::RefCell, fmt, io, panic, pin::Pin, rc::Rc};
3
4use crate::rt::Runtime;
5
6pub type BlockFuture = Pin<Box<dyn Future<Output = ()>>>;
7
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9pub enum DriverType {
10 Poll,
11 IoUring,
12 Iocp,
13}
14
15impl DriverType {
16 pub const fn name(&self) -> &'static str {
17 match self {
18 DriverType::Poll => "polling",
19 DriverType::IoUring => "io-uring",
20 DriverType::Iocp => "iocp",
21 }
22 }
23
24 pub const fn is_polling(&self) -> bool {
25 matches!(self, &DriverType::Poll)
26 }
27}
28
29pub trait Runner: Send + Sync + 'static {
30 fn block_on(&self, fut: BlockFuture) -> Result<(), Box<dyn Any + Send>>;
31}
32
33pub trait Driver: 'static {
34 fn handle(&self) -> Box<dyn Notify>;
35
36 fn run(&self, rt: &Runtime) -> io::Result<()>;
37
38 fn clear(&self) {}
39}
40
41#[derive(Copy, Clone, Debug, PartialEq, Eq)]
42pub enum PollResult {
43 Ready,
44 Pending,
45 PollAgain,
46}
47
48pub trait Notify: Send + Sync + fmt::Debug + 'static {
49 fn notify(&self) -> io::Result<()>;
50}
51
52#[cfg(windows)]
53#[macro_export]
54macro_rules! syscall {
55 (BOOL, $e:expr) => {
56 $crate::syscall!($e, == 0)
57 };
58 (SOCKET, $e:expr) => {
59 $crate::syscall!($e, != 0)
60 };
61 (HANDLE, $e:expr) => {
62 $crate::syscall!($e, == ::windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE)
63 };
64 ($e:expr, $op: tt $rhs: expr) => {{
65 #[allow(unused_unsafe)]
66 let res = unsafe { $e };
67 if res $op $rhs {
68 Err(::std::io::Error::last_os_error())
69 } else {
70 Ok(res)
71 }
72 }};
73}
74
75#[cfg(unix)]
77#[macro_export]
78macro_rules! syscall {
79 (break $e:expr) => {
80 loop {
81 match $crate::syscall!($e) {
82 Ok(fd) => break ::std::task::Poll::Ready(Ok(fd as usize)),
83 Err(e) if e.kind() == ::std::io::ErrorKind::WouldBlock || e.raw_os_error() == Some(::libc::EINPROGRESS)
84 => break ::std::task::Poll::Pending,
85 Err(e) if e.kind() == ::std::io::ErrorKind::Interrupted => {},
86 Err(e) => break ::std::task::Poll::Ready(Err(e)),
87 }
88 }
89 };
90 ($e:expr, $f:ident($fd:expr)) => {
91 match $crate::syscall!(break $e) {
92 ::std::task::Poll::Pending => Ok($crate::sys::Decision::$f($fd)),
93 ::std::task::Poll::Ready(Ok(res)) => Ok($crate::sys::Decision::Completed(res)),
94 ::std::task::Poll::Ready(Err(e)) => Err(e),
95 }
96 };
97 ($e:expr) => {{
98 #[allow(unused_unsafe)]
99 let res = unsafe { $e };
100 if res == -1 {
101 Err(::std::io::Error::last_os_error())
102 } else {
103 Ok(res)
104 }
105 }};
106}
107
108pub(super) fn block_on<F, R>(run: &dyn Runner, fut: F) -> Result<R, Box<dyn Any + Send>>
110where
111 F: Future<Output = R> + 'static,
112 R: 'static,
113{
114 let result = Rc::new(RefCell::new(None));
116 let result_inner = result.clone();
117
118 ntex_error::set_backtrace_start_alt("ntex/ntex-rt/src/driver.rs", 0);
119 run.block_on(Box::pin(async move {
120 let r = fut.await;
121 *result_inner.borrow_mut() = Some(r);
122 }))?;
123
124 unsafe {
125 crate::remove_all_items();
126 }
127 Ok(result.borrow_mut().take().unwrap())
128}
129
130pub(super) fn block_on_panic<F, R>(run: &dyn Runner, fut: F) -> R
131where
132 F: Future<Output = R> + 'static,
133 R: 'static,
134{
135 match block_on(run, fut) {
136 Ok(v) => v,
137 Err(e) => panic::resume_unwind(e),
138 }
139}