Skip to main content

compio_driver/sys/driver/poll/
op.rs

1pub use self::OpCode as PollOpCode;
2use crate::sys::prelude::*;
3
4/// Represents the filter type of kqueue. `polling` crate doesn't expose such
5/// API, and we need to know about it when `cancel` is called.
6#[non_exhaustive]
7pub enum OpType {
8    /// The operation polls an fd.
9    Fd(Multi<RawFd>),
10    /// The operation submits an AIO.
11    #[cfg(aio)]
12    Aio(NonNull<libc::aiocb>),
13}
14
15/// Result of [`OpCode::pre_submit`].
16#[derive(Debug)]
17#[non_exhaustive]
18pub enum Decision {
19    /// Instant operation, no need to submit
20    Completed(usize),
21    /// Async operation, needs to submit
22    Wait(Multi<WaitArg>),
23    /// Blocking operation, needs to be spawned in another thread
24    Blocking,
25    /// AIO operation, needs to be spawned to the kernel.
26    #[cfg(aio)]
27    Aio(AioArg),
28}
29
30/// Meta of polling operations.
31#[derive(Debug, Clone, Copy)]
32pub struct WaitArg {
33    /// The raw fd of the operation.
34    pub fd: RawFd,
35    /// The interest to be registered.
36    pub interest: Interest,
37}
38
39/// Abstraction of operations.
40///
41/// # Safety
42///
43/// If `pre_submit` returns `Decision::Wait`, `op_type` must also return
44/// `Some(OpType::Fd)` with same fds as the `WaitArg`s. Similarly, if
45/// `pre_submit` returns `Decision::Aio`, `op_type` must return
46/// `Some(OpType::Aio)` with the correct `aiocb` pointer.
47pub unsafe trait OpCode {
48    /// Type that contains self-references and other needed info during the
49    /// operation
50    type Control: Default;
51
52    /// Initialize the control
53    ///
54    /// # Safety
55    ///
56    /// Caller must guarantee that during the lifetime of `ctrl`, `Self` is
57    /// unmoved and valid.
58    unsafe fn init(&mut self, _: &mut Self::Control) {}
59
60    /// Perform the operation before submit, and return [`Decision`] to
61    /// indicate whether submitting the operation to polling is required.
62    fn pre_submit(&mut self, _: &mut Self::Control) -> io::Result<Decision>;
63
64    /// Get the operation type when an event is occurred.
65    fn op_type(&mut self, _: &mut Self::Control) -> Option<OpType> {
66        None
67    }
68
69    /// Perform the operation after received corresponding
70    /// event. If this operation is blocking, the return value should be
71    /// [`Poll::Ready`].
72    fn operate(&mut self, _: &mut Self::Control) -> Poll<io::Result<usize>>;
73
74    /// Set the result when it completes.
75    /// The operation stores the result and is responsible to release it if
76    /// the operation is cancelled.
77    ///
78    /// # Safety
79    ///
80    /// The params must be the result coming from this operation.
81    unsafe fn set_result(
82        &mut self,
83        _: &mut Self::Control,
84        _: &io::Result<usize>,
85        _: &crate::Extra,
86    ) {
87    }
88}
89
90pub(crate) trait Carry {
91    fn pre_submit(&mut self) -> io::Result<Decision>;
92    fn op_type(&mut self) -> Option<OpType>;
93    fn operate(&mut self) -> Poll<io::Result<usize>>;
94    unsafe fn set_result(&mut self, _: &io::Result<usize>, _: &crate::Extra);
95}
96
97impl OpType {
98    /// Create an [`OpType::Fd`] with one [`RawFd`].
99    pub fn fd(fd: RawFd) -> Self {
100        Self::Fd(Multi::from_buf([fd]))
101    }
102
103    /// Create an [`OpType::Fd`] with multiple [`RawFd`]s.
104    pub fn multi_fd<I: IntoIterator<Item = RawFd>>(fds: I) -> Self {
105        Self::Fd(Multi::from_iter(fds))
106    }
107}
108
109impl<T: crate::OpCode> Carry for Carrier<T> {
110    fn pre_submit(&mut self) -> io::Result<Decision> {
111        let (op, control) = self.as_poll();
112        op.pre_submit(control)
113    }
114
115    fn op_type(&mut self) -> Option<OpType> {
116        let (op, control) = self.as_poll();
117        op.op_type(control)
118    }
119
120    fn operate(&mut self) -> Poll<io::Result<usize>> {
121        let (op, control) = self.as_poll();
122        op.operate(control)
123    }
124
125    unsafe fn set_result(&mut self, res: &io::Result<usize>, extra: &crate::Extra) {
126        let (op, control) = self.as_poll();
127        unsafe { OpCode::set_result(op, control, res, extra) }
128    }
129}
130
131impl Decision {
132    /// Decide to wait for the given fd with the given interest.
133    pub fn wait_for(fd: RawFd, interest: Interest) -> Self {
134        Self::Wait(Multi::from_buf([WaitArg { fd, interest }]))
135    }
136
137    /// Decide to wait for many fds.
138    pub fn wait_for_many<I: IntoIterator<Item = WaitArg>>(args: I) -> Self {
139        Self::Wait(Multi::from_iter(args))
140    }
141
142    /// Decide to wait for the given fd to be readable.
143    pub fn wait_readable(fd: RawFd) -> Self {
144        Self::wait_for(fd, Interest::Readable)
145    }
146
147    /// Decide to wait for the given fd to be writable.
148    pub fn wait_writable(fd: RawFd) -> Self {
149        Self::wait_for(fd, Interest::Writable)
150    }
151
152    /// Decide to spawn an AIO operation. `submit` is a method like
153    /// `aio_read`.
154    #[cfg(aio)]
155    pub fn aio(
156        cb: &mut libc::aiocb,
157        submit: unsafe extern "C" fn(*mut libc::aiocb) -> i32,
158    ) -> Self {
159        Self::Aio(AioArg {
160            aiocbp: NonNull::from(cb),
161            submit,
162        })
163    }
164}
165
166impl WaitArg {
167    /// Create a new readable `WaitArg`.
168    pub fn readable(fd: RawFd) -> Self {
169        Self {
170            fd,
171            interest: Interest::Readable,
172        }
173    }
174
175    /// Create a new writable `WaitArg`.
176    pub fn writable(fd: RawFd) -> Self {
177        Self {
178            fd,
179            interest: Interest::Writable,
180        }
181    }
182}