1#![cfg_attr(any(windows, target_os = "linux"), expect(unsafe_code))]
8
9#[cfg(unix)]
10use crate::fd::FdReadyDriver;
11#[cfg(unix)]
12use crate::fd::PollFdReady;
13#[cfg(target_os = "linux")]
14use crate::io_uring::IoUringDriver;
15#[cfg(target_os = "macos")]
16use crate::process::macos::PollProcessWait;
17#[cfg(target_os = "macos")]
18use crate::process::macos::ProcessWaitDriver;
19use crate::socket::PollSocketReady;
20use crate::socket::SocketReadyDriver;
21#[cfg(windows)]
22use crate::sys::overlapped::IoOverlapped;
23#[cfg(windows)]
24use crate::sys::overlapped::OverlappedIoDriver;
25use crate::task::Spawn;
26use crate::timer::PollTimer;
27use crate::timer::TimerDriver;
28use crate::wait::PollWait;
29use crate::wait::WaitDriver;
30use smallbox::SmallBox;
31use smallbox::space::S4;
32use std::io;
33#[cfg(unix)]
34use std::os::unix::prelude::*;
35#[cfg(windows)]
36use std::os::windows::prelude::*;
37use std::sync::Arc;
38
39pub type PollImpl<T> = SmallBox<T, S4>;
41
42pub trait Driver: 'static + Send + Sync {
44 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer>;
46
47 #[cfg(unix)]
49 fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>>;
50
51 #[cfg(windows)]
53 fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>>;
54
55 #[cfg(unix)]
57 fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>>;
58
59 #[cfg(windows)]
61 fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>>;
62
63 #[cfg(unix)]
69 fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>>;
70
71 #[cfg(target_os = "macos")]
73 fn new_dyn_process_wait(&self, pid: i32) -> io::Result<PollImpl<dyn PollProcessWait>>;
74
75 #[cfg(windows)]
81 unsafe fn new_dyn_overlapped_file(
82 &self,
83 handle: RawHandle,
84 ) -> io::Result<PollImpl<dyn IoOverlapped>>;
85
86 #[cfg(target_os = "linux")]
88 fn io_uring_probe(&self, opcode: u8) -> bool;
89
90 #[cfg(target_os = "linux")]
135 unsafe fn io_uring_submit(
136 &self,
137 sqe: crate::io_uring::Entry,
138 ) -> std::pin::Pin<Box<dyn Future<Output = io::Result<i32>> + Send + '_>>;
139}
140
141#[cfg(target_os = "macos")]
142impl<T> Driver for T
143where
144 T: 'static
145 + Send
146 + Sync
147 + FdReadyDriver
148 + TimerDriver
149 + SocketReadyDriver
150 + WaitDriver
151 + ProcessWaitDriver,
152{
153 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
154 smallbox::smallbox!(self.new_timer())
155 }
156
157 fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>> {
158 Ok(smallbox::smallbox!(self.new_fd_ready(fd)?))
159 }
160
161 fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>> {
162 Ok(smallbox::smallbox!(self.new_socket_ready(socket)?))
163 }
164
165 fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>> {
166 Ok(smallbox::smallbox!(self.new_wait(fd, read_size)?))
167 }
168
169 fn new_dyn_process_wait(&self, pid: i32) -> io::Result<PollImpl<dyn PollProcessWait>> {
170 Ok(smallbox::smallbox!(self.new_process_wait_pid(pid)?))
171 }
172}
173
174#[cfg(target_os = "linux")]
175impl<T> Driver for T
176where
177 T: 'static
178 + Send
179 + Sync
180 + FdReadyDriver
181 + TimerDriver
182 + SocketReadyDriver
183 + WaitDriver
184 + IoUringDriver,
185{
186 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
187 smallbox::smallbox!(self.new_timer())
188 }
189
190 fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>> {
191 Ok(smallbox::smallbox!(self.new_fd_ready(fd)?))
192 }
193
194 fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>> {
195 Ok(smallbox::smallbox!(self.new_socket_ready(socket)?))
196 }
197
198 fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>> {
199 Ok(smallbox::smallbox!(self.new_wait(fd, read_size)?))
200 }
201
202 fn io_uring_probe(&self, opcode: u8) -> bool {
203 use crate::io_uring::IoUringSubmit as _;
204
205 self.io_uring_submitter()
206 .is_some_and(|submitter| submitter.probe(opcode))
207 }
208
209 unsafe fn io_uring_submit(
210 &self,
211 sqe: crate::io_uring::Entry,
212 ) -> std::pin::Pin<Box<dyn Future<Output = io::Result<i32>> + Send + '_>> {
213 use crate::io_uring::IoUringSubmit as _;
214
215 Box::pin(async move {
216 unsafe {
218 self.io_uring_submitter()
219 .ok_or(io::ErrorKind::Unsupported)?
220 .submit(sqe)
221 }
222 .await
223 })
224 }
225}
226
227#[cfg(windows)]
228impl<T> Driver for T
229where
230 T: 'static + Send + Sync + TimerDriver + SocketReadyDriver + WaitDriver + OverlappedIoDriver,
231{
232 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
233 smallbox::smallbox!(self.new_timer())
234 }
235
236 fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>> {
237 Ok(smallbox::smallbox!(self.new_socket_ready(socket)?))
238 }
239
240 fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>> {
241 Ok(smallbox::smallbox!(self.new_wait(handle)?))
242 }
243
244 unsafe fn new_dyn_overlapped_file(
245 &self,
246 handle: RawHandle,
247 ) -> io::Result<PollImpl<dyn IoOverlapped>> {
248 Ok(smallbox::smallbox!(unsafe {
250 self.new_overlapped_file(handle)
251 }?))
252 }
253}
254
255#[cfg(unix)]
256impl Driver for Box<dyn Driver> {
257 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
258 self.as_ref().new_dyn_timer()
259 }
260
261 fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>> {
262 self.as_ref().new_dyn_fd_ready(fd)
263 }
264
265 fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>> {
266 self.as_ref().new_dyn_socket_ready(socket)
267 }
268
269 fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>> {
270 self.as_ref().new_dyn_wait(fd, read_size)
271 }
272
273 #[cfg(target_os = "macos")]
274 fn new_dyn_process_wait(&self, pid: i32) -> io::Result<PollImpl<dyn PollProcessWait>> {
275 self.as_ref().new_dyn_process_wait(pid)
276 }
277
278 #[cfg(target_os = "linux")]
279 fn io_uring_probe(&self, opcode: u8) -> bool {
280 self.as_ref().io_uring_probe(opcode)
281 }
282
283 #[cfg(target_os = "linux")]
284 unsafe fn io_uring_submit(
285 &self,
286 sqe: crate::io_uring::Entry,
287 ) -> std::pin::Pin<Box<dyn Future<Output = io::Result<i32>> + Send + '_>> {
288 unsafe { self.as_ref().io_uring_submit(sqe) }
290 }
291}
292
293#[cfg(windows)]
294impl Driver for Box<dyn Driver> {
295 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
296 self.as_ref().new_dyn_timer()
297 }
298
299 fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>> {
300 self.as_ref().new_dyn_socket_ready(socket)
301 }
302
303 fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>> {
304 self.as_ref().new_dyn_wait(handle)
305 }
306
307 unsafe fn new_dyn_overlapped_file(
308 &self,
309 handle: RawHandle,
310 ) -> io::Result<PollImpl<dyn IoOverlapped>> {
311 unsafe { self.as_ref().new_dyn_overlapped_file(handle) }
313 }
314}
315
316#[cfg(unix)]
317impl Driver for Arc<dyn Driver> {
318 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
319 self.as_ref().new_dyn_timer()
320 }
321
322 fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>> {
323 self.as_ref().new_dyn_fd_ready(fd)
324 }
325
326 fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>> {
327 self.as_ref().new_dyn_socket_ready(socket)
328 }
329
330 fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>> {
331 self.as_ref().new_dyn_wait(fd, read_size)
332 }
333
334 #[cfg(target_os = "macos")]
335 fn new_dyn_process_wait(&self, pid: i32) -> io::Result<PollImpl<dyn PollProcessWait>> {
336 self.as_ref().new_dyn_process_wait(pid)
337 }
338
339 #[cfg(target_os = "linux")]
340 fn io_uring_probe(&self, opcode: u8) -> bool {
341 self.as_ref().io_uring_probe(opcode)
342 }
343
344 #[cfg(target_os = "linux")]
345 unsafe fn io_uring_submit(
346 &self,
347 sqe: crate::io_uring::Entry,
348 ) -> std::pin::Pin<Box<dyn Future<Output = io::Result<i32>> + Send + '_>> {
349 unsafe { self.as_ref().io_uring_submit(sqe) }
351 }
352}
353
354#[cfg(windows)]
355impl Driver for Arc<dyn Driver> {
356 fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
357 self.as_ref().new_dyn_timer()
358 }
359
360 fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>> {
361 self.as_ref().new_dyn_socket_ready(socket)
362 }
363
364 fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>> {
365 self.as_ref().new_dyn_wait(handle)
366 }
367
368 unsafe fn new_dyn_overlapped_file(
369 &self,
370 handle: RawHandle,
371 ) -> io::Result<PollImpl<dyn IoOverlapped>> {
372 unsafe { self.as_ref().new_dyn_overlapped_file(handle) }
374 }
375}
376
377pub trait SpawnDriver: Spawn + Driver {}
379
380impl<T: Spawn + Driver> SpawnDriver for T {}