pal_async/
driver.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Driver trait.
5
6// UNSAFETY: Needed to define and implement the unsafe new_dyn_overlapped_file method.
7#![cfg_attr(windows, expect(unsafe_code))]
8
9#[cfg(unix)]
10use crate::fd::FdReadyDriver;
11#[cfg(unix)]
12use crate::fd::PollFdReady;
13use crate::socket::PollSocketReady;
14use crate::socket::SocketReadyDriver;
15#[cfg(windows)]
16use crate::sys::overlapped::IoOverlapped;
17#[cfg(windows)]
18use crate::sys::overlapped::OverlappedIoDriver;
19use crate::task::Spawn;
20use crate::timer::PollTimer;
21use crate::timer::TimerDriver;
22use crate::wait::PollWait;
23use crate::wait::WaitDriver;
24use smallbox::SmallBox;
25use smallbox::space::S4;
26use std::io;
27#[cfg(unix)]
28use std::os::unix::prelude::*;
29#[cfg(windows)]
30use std::os::windows::prelude::*;
31use std::sync::Arc;
32
33/// A generic `Box`-like container of one of the polled types.
34pub type PollImpl<T> = SmallBox<T, S4>;
35
36/// A driver that supports polled IO.
37pub trait Driver: 'static + Send + Sync {
38    /// Returns a new timer.
39    fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer>;
40
41    /// Returns a new object for polling file descriptor readiness.
42    #[cfg(unix)]
43    fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>>;
44
45    /// Creates a new object for polling socket readiness.
46    #[cfg(windows)]
47    fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>>;
48
49    /// Creates a new object for polling socket readiness.
50    #[cfg(unix)]
51    fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>>;
52
53    /// Creates a new wait.
54    #[cfg(windows)]
55    fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>>;
56
57    /// Creates a new wait.
58    ///
59    /// Signals will be consumed using reads of `read_size` bytes, with 8-byte
60    /// buffer alignment. `read_size` must be at most
61    /// [`MAXIMUM_WAIT_READ_SIZE`](super::wait::MAXIMUM_WAIT_READ_SIZE) bytes.
62    #[cfg(unix)]
63    fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>>;
64
65    /// Creates a new overlapped file handler.
66    ///
67    /// # Safety
68    /// The caller must ensure that they exclusively own `handle`, and that
69    /// `handle` stays alive until the new handler is dropped.
70    #[cfg(windows)]
71    unsafe fn new_dyn_overlapped_file(
72        &self,
73        handle: RawHandle,
74    ) -> io::Result<PollImpl<dyn IoOverlapped>>;
75}
76
77#[cfg(unix)]
78impl<T> Driver for T
79where
80    T: 'static + Send + Sync + FdReadyDriver + TimerDriver + SocketReadyDriver + WaitDriver,
81{
82    fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
83        smallbox::smallbox!(self.new_timer())
84    }
85
86    fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>> {
87        Ok(smallbox::smallbox!(self.new_fd_ready(fd)?))
88    }
89
90    fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>> {
91        Ok(smallbox::smallbox!(self.new_socket_ready(socket)?))
92    }
93
94    fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>> {
95        Ok(smallbox::smallbox!(self.new_wait(fd, read_size)?))
96    }
97}
98
99#[cfg(windows)]
100impl<T> Driver for T
101where
102    T: 'static + Send + Sync + TimerDriver + SocketReadyDriver + WaitDriver + OverlappedIoDriver,
103{
104    fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
105        smallbox::smallbox!(self.new_timer())
106    }
107
108    fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>> {
109        Ok(smallbox::smallbox!(self.new_socket_ready(socket)?))
110    }
111
112    fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>> {
113        Ok(smallbox::smallbox!(self.new_wait(handle)?))
114    }
115
116    unsafe fn new_dyn_overlapped_file(
117        &self,
118        handle: RawHandle,
119    ) -> io::Result<PollImpl<dyn IoOverlapped>> {
120        // SAFETY: caller guarantees contract
121        Ok(smallbox::smallbox!(unsafe {
122            self.new_overlapped_file(handle)
123        }?))
124    }
125}
126
127#[cfg(unix)]
128impl Driver for Box<dyn Driver> {
129    fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
130        self.as_ref().new_dyn_timer()
131    }
132
133    fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>> {
134        self.as_ref().new_dyn_fd_ready(fd)
135    }
136
137    fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>> {
138        self.as_ref().new_dyn_socket_ready(socket)
139    }
140
141    fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>> {
142        self.as_ref().new_dyn_wait(fd, read_size)
143    }
144}
145
146#[cfg(windows)]
147impl Driver for Box<dyn Driver> {
148    fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
149        self.as_ref().new_dyn_timer()
150    }
151
152    fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>> {
153        self.as_ref().new_dyn_socket_ready(socket)
154    }
155
156    fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>> {
157        self.as_ref().new_dyn_wait(handle)
158    }
159
160    unsafe fn new_dyn_overlapped_file(
161        &self,
162        handle: RawHandle,
163    ) -> io::Result<PollImpl<dyn IoOverlapped>> {
164        // SAFETY: caller guarantees contract
165        unsafe { self.as_ref().new_dyn_overlapped_file(handle) }
166    }
167}
168
169#[cfg(unix)]
170impl Driver for Arc<dyn Driver> {
171    fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
172        self.as_ref().new_dyn_timer()
173    }
174
175    fn new_dyn_fd_ready(&self, fd: RawFd) -> io::Result<PollImpl<dyn PollFdReady>> {
176        self.as_ref().new_dyn_fd_ready(fd)
177    }
178
179    fn new_dyn_socket_ready(&self, socket: RawFd) -> io::Result<PollImpl<dyn PollSocketReady>> {
180        self.as_ref().new_dyn_socket_ready(socket)
181    }
182
183    fn new_dyn_wait(&self, fd: RawFd, read_size: usize) -> io::Result<PollImpl<dyn PollWait>> {
184        self.as_ref().new_dyn_wait(fd, read_size)
185    }
186}
187
188#[cfg(windows)]
189impl Driver for Arc<dyn Driver> {
190    fn new_dyn_timer(&self) -> PollImpl<dyn PollTimer> {
191        self.as_ref().new_dyn_timer()
192    }
193
194    fn new_dyn_socket_ready(&self, socket: RawSocket) -> io::Result<PollImpl<dyn PollSocketReady>> {
195        self.as_ref().new_dyn_socket_ready(socket)
196    }
197
198    fn new_dyn_wait(&self, handle: RawHandle) -> io::Result<PollImpl<dyn PollWait>> {
199        self.as_ref().new_dyn_wait(handle)
200    }
201
202    unsafe fn new_dyn_overlapped_file(
203        &self,
204        handle: RawHandle,
205    ) -> io::Result<PollImpl<dyn IoOverlapped>> {
206        // SAFETY: caller guarantees contract
207        unsafe { self.as_ref().new_dyn_overlapped_file(handle) }
208    }
209}
210
211/// Trait for [`Driver`]s that also implement [`Spawn`].
212pub trait SpawnDriver: Spawn + Driver {}
213
214impl<T: Spawn + Driver> SpawnDriver for T {}