Skip to main content

compio_driver/sys/fusion/
op.rs

1use std::{ffi::CString, hint::unreachable_unchecked};
2
3use compio_buf::{IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
4use socket2::SockAddr;
5
6use super::*;
7pub use crate::sys::unix_op::*;
8
9macro_rules! op {
10    (<$($ty:ident: $trait:ident),* $(,)?> $name:ident( $($arg:ident: $arg_t:ty),* $(,)? )) => {
11        ::paste::paste!{
12            enum [< $name Inner >] <$($ty: $trait),*> {
13                Uninit($($arg_t),*),
14                Poll(poll::$name<$($ty),*>),
15                IoUring(iour::$name<$($ty),*>),
16            }
17
18            impl<$($ty: $trait),*> [< $name Inner >]<$($ty),*> {
19                fn poll(&mut self) -> &mut poll::$name<$($ty),*> {
20                    match self {
21                        Self::Uninit(..) => {
22                            unsafe {
23                                let Self::Uninit($($arg),*) = std::ptr::read(self) else {
24                                    unreachable_unchecked()
25                                };
26                                std::ptr::write(self, Self::Poll(poll::$name::new($($arg),*)));
27                            }
28                            self.poll()
29                        },
30                        Self::Poll(op) => op,
31                        Self::IoUring(_) => unreachable!("Current driver is not `polling`"),
32                    }
33                }
34
35                fn iour(&mut self) -> &mut iour::$name<$($ty),*> {
36                    match self {
37                        Self::Uninit(..) => {
38                            unsafe {
39                                let Self::Uninit($($arg),*) = std::ptr::read(self) else {
40                                    unreachable_unchecked()
41                                };
42                                std::ptr::write(self, Self::IoUring(iour::$name::new($($arg),*)));
43                            }
44                            self.iour()
45                        },
46                        Self::IoUring(op) => op,
47                        Self::Poll(_) => unreachable!("Current driver is not `io-uring`"),
48                    }
49                }
50            }
51
52            #[doc = concat!("A fused `", stringify!($name), "` operation")]
53            pub struct $name <$($ty: $trait),*> {
54                inner: [< $name Inner >] <$($ty),*>
55            }
56
57            impl<$($ty: $trait),*> IntoInner for $name <$($ty),*> {
58                type Inner = <poll::$name<$($ty),*> as IntoInner>::Inner;
59
60                fn into_inner(mut self) -> Self::Inner {
61                    match self.inner {
62                        [< $name Inner >]::Uninit(..) => {
63                            self.inner.poll();
64                            self.into_inner()
65                        },
66                        [< $name Inner >]::Poll(op) => op.into_inner(),
67                        [< $name Inner >]::IoUring(op) => op.into_inner(),
68                    }
69                }
70            }
71
72            impl<$($ty: $trait),*> $name <$($ty),*> {
73                #[doc = concat!("Create a new `", stringify!($name), "`.")]
74                pub fn new($($arg: $arg_t),*) -> Self {
75                    Self { inner: [< $name Inner >]::Uninit($($arg),*) }
76                }
77            }
78        }
79
80        unsafe impl<$($ty: $trait),*> poll::OpCode for $name<$($ty),*> {
81            fn pre_submit(self: std::pin::Pin<&mut Self>) -> std::io::Result<crate::Decision> {
82                unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.pre_submit()
83            }
84
85            fn op_type(self: std::pin::Pin<&mut Self>) -> Option<OpType> {
86                unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.op_type()
87            }
88
89            fn operate(
90                self: std::pin::Pin<&mut Self>,
91            ) -> std::task::Poll<std::io::Result<usize>> {
92                unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.operate()
93            }
94        }
95
96        unsafe impl<$($ty: $trait),*> iour::OpCode for $name<$($ty),*> {
97            fn create_entry(self: std::pin::Pin<&mut Self>) -> OpEntry {
98                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.create_entry()
99            }
100
101            fn create_entry_fallback(self: std::pin::Pin<&mut Self>) -> OpEntry {
102                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.create_entry_fallback()
103            }
104
105            fn call_blocking(self: std::pin::Pin<&mut Self>) -> std::io::Result<usize> {
106                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.call_blocking()
107            }
108
109            unsafe fn set_result(self: std::pin::Pin<&mut Self>, result: &std::io::Result<usize>, extra: &crate::Extra) {
110                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ).set_result(result, extra) }
111            }
112
113            unsafe fn push_multishot(self: std::pin::Pin<&mut Self>, result: std::io::Result<usize>, extra: crate::Extra) {
114                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ).push_multishot(result, extra) }
115            }
116
117            fn pop_multishot(self: std::pin::Pin<&mut Self>) -> Option<BufResult<usize, crate::Extra>> {
118                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.pop_multishot()
119            }
120        }
121    };
122}
123
124#[rustfmt::skip]
125mod iour { pub use crate::sys::iour::{op::*, OpCode}; }
126#[rustfmt::skip]
127mod poll { pub use crate::sys::poll::{op::*, OpCode}; }
128
129op!(<S: AsFd> AcceptMulti(fd: S));
130op!(<T: IoBufMut, S: AsFd> RecvFrom(fd: S, buffer: T, flags: i32));
131op!(<T: IoBuf, S: AsFd> SendTo(fd: S, buffer: T, addr: SockAddr, flags: i32));
132op!(<T: IoVectoredBufMut, S: AsFd> RecvFromVectored(fd: S, buffer: T, flags: i32));
133op!(<T: IoVectoredBuf, S: AsFd> SendToVectored(fd: S, buffer: T, addr: SockAddr, flags: i32));
134op!(<S: AsFd> FileStat(fd: S));
135op!(<S: AsFd> PathStat(dirfd: S, path: CString, follow_symlink: bool));
136op!(<T: IoBuf, S: AsFd> SendZc(fd: S, buffer: T, flags: i32));
137op!(<T: IoVectoredBuf, S: AsFd> SendVectoredZc(fd: S, buffer: T, flags: i32));
138op!(<T: IoBuf, S: AsFd> SendToZc(fd: S, buffer: T, addr: SockAddr, flags: i32));
139op!(<T: IoVectoredBuf, S: AsFd> SendToVectoredZc(fd: S, buffer: T, addr: SockAddr, flags: i32));
140op!(<T: IoVectoredBuf, C: IoBuf, S: AsFd> SendMsgZc(fd: S, buffer: T, control: C, addr: Option<SockAddr>, flags: i32));
141
142macro_rules! mop {
143    (<$($ty:ident: $trait:ident),* $(,)?> $name:ident( $($arg:ident: $arg_t:ty),* $(,)? ) with $pool:ident) => {
144        mop!{ < $($ty: $trait),* > $name ( $( $arg: $arg_t ),* ) with $pool, buffer: crate::BorrowedBuffer<'a> }
145    };
146    (<$($ty:ident: $trait:ident),* $(,)?> $name:ident( $($arg:ident: $arg_t:ty),* $(,)? ) with $pool:ident, buffer: $buffer:ty) => {
147        ::paste::paste!{
148            enum [< $name Inner >] <$($ty: $trait),*> {
149                Poll(crate::op::managed::$name<$($ty),*>),
150                IoUring(iour::$name<$($ty),*>),
151            }
152
153            impl<$($ty: $trait),*> [< $name Inner >]<$($ty),*> {
154                fn poll(&mut self) -> &mut crate::op::managed::$name<$($ty),*> {
155                    match self {
156                        Self::Poll(op) => op,
157                        Self::IoUring(_) => unreachable!("Current driver is not `io-uring`"),
158                    }
159                }
160
161                fn iour(&mut self) -> &mut iour::$name<$($ty),*> {
162                    match self {
163                        Self::IoUring(op) => op,
164                        Self::Poll(_) => unreachable!("Current driver is not `polling`"),
165                    }
166                }
167            }
168
169            #[doc = concat!("A fused `", stringify!($name), "` operation")]
170            pub struct $name <$($ty: $trait),*> {
171                inner: [< $name Inner >] <$($ty),*>
172            }
173
174            impl<$($ty: $trait),*> $name <$($ty),*> {
175                #[doc = concat!("Create a new `", stringify!($name), "`.")]
176                pub fn new($($arg: $arg_t),*) -> std::io::Result<Self> {
177                    Ok(if $pool.is_io_uring() {
178                        Self {
179                            inner: [< $name Inner >]::IoUring(iour::$name::new($($arg),*)?),
180                        }
181                    } else {
182                        Self {
183                            inner: [< $name Inner >]::Poll(crate::op::managed::$name::new($($arg),*)?),
184                        }
185                    })
186                }
187            }
188
189            impl<$($ty: $trait),*> crate::TakeBuffer for $name<$($ty),*> {
190                type BufferPool = crate::BufferPool;
191                type Buffer<'a> = $buffer;
192
193                fn take_buffer(
194                    self,
195                    buffer_pool: &Self::BufferPool,
196                    result: io::Result<usize>,
197                    buffer_id: u16,
198                ) -> io::Result<Self::Buffer<'_>> {
199                    match self.inner {
200                        [< $name Inner >]::Poll(inner) => {
201                            Ok(inner.take_buffer(buffer_pool, result, buffer_id)?)
202                        }
203                        [< $name Inner >]::IoUring(inner) => {
204                            Ok(inner.take_buffer(buffer_pool, result, buffer_id)?)
205                        }
206                    }
207                }
208            }
209        }
210
211        unsafe impl<$($ty: $trait),*> poll::OpCode for $name<$($ty),*> {
212            fn pre_submit(self: std::pin::Pin<&mut Self>) -> std::io::Result<crate::Decision> {
213                unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.pre_submit()
214            }
215
216            fn op_type(self: std::pin::Pin<&mut Self>) -> Option<OpType> {
217                unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.op_type()
218            }
219
220            fn operate(
221                self: std::pin::Pin<&mut Self>,
222            ) -> std::task::Poll<std::io::Result<usize>> {
223                unsafe { self.map_unchecked_mut(|x| x.inner.poll() ) }.operate()
224            }
225        }
226
227        unsafe impl<$($ty: $trait),*> iour::OpCode for $name<$($ty),*> {
228            fn create_entry(self: std::pin::Pin<&mut Self>) -> OpEntry {
229                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.create_entry()
230            }
231
232            fn create_entry_fallback(self: std::pin::Pin<&mut Self>) -> OpEntry {
233                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.create_entry_fallback()
234            }
235
236            fn call_blocking(self: std::pin::Pin<&mut Self>) -> std::io::Result<usize> {
237                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.call_blocking()
238            }
239
240            unsafe fn set_result(self: std::pin::Pin<&mut Self>, result: &std::io::Result<usize>, extra: &crate::Extra) {
241                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ).set_result(result, extra) }
242            }
243
244            unsafe fn push_multishot(self: std::pin::Pin<&mut Self>, result: std::io::Result<usize>, extra: crate::Extra) {
245                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ).push_multishot(result, extra) }
246            }
247
248            fn pop_multishot(self: std::pin::Pin<&mut Self>) -> Option<BufResult<usize, crate::Extra>> {
249                unsafe { self.map_unchecked_mut(|x| x.inner.iour() ) }.pop_multishot()
250            }
251        }
252    };
253}
254
255mop!(<S: AsFd> ReadManagedAt(fd: S, offset: u64, pool: &BufferPool, len: usize) with pool);
256mop!(<S: AsFd> ReadManaged(fd: S, pool: &BufferPool, len: usize) with pool);
257mop!(<S: AsFd> RecvManaged(fd: S, pool: &BufferPool, len: usize, flags: i32) with pool);
258mop!(<S: AsFd> RecvFromManaged(fd: S, pool: &BufferPool, len: usize, flags: i32) with pool, buffer: (crate::BorrowedBuffer<'a>, Option<SockAddr>));
259mop!(<S: AsFd> ReadMultiAt(fd: S, offset: u64, pool: &BufferPool, len: usize) with pool);
260mop!(<S: AsFd> ReadMulti(fd: S, pool: &BufferPool, len: usize) with pool);
261mop!(<S: AsFd> RecvMulti(fd: S, pool: &BufferPool, len: usize, flags: i32) with pool);