compio_driver/sys/fusion/
mod.rs1pub(crate) mod op;
2
3#[cfg_attr(all(doc, docsrs), doc(cfg(all())))]
4pub use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
5use std::{
6 io,
7 task::{Poll, Waker},
8 time::Duration,
9};
10
11use compio_log::warn;
12pub use iour::{IourOpCode, OpEntry};
13pub use poll::{Decision, OpType, PollOpCode};
14
15pub(crate) use super::iour::is_op_supported;
16use super::{iour, poll};
17pub use crate::driver_type::DriverType; use crate::{BufferPool, Key, ProactorBuilder, key::ErasedKey};
19
20pub enum Extra {
21 Poll(poll::Extra),
22 IoUring(iour::Extra),
23}
24
25impl From<poll::Extra> for Extra {
26 fn from(inner: poll::Extra) -> Self {
27 Self::Poll(inner)
28 }
29}
30
31impl From<iour::Extra> for Extra {
32 fn from(inner: iour::Extra) -> Self {
33 Self::IoUring(inner)
34 }
35}
36
37#[allow(dead_code)]
38impl super::Extra {
39 pub(in crate::sys) fn try_as_iour(&self) -> Option<&iour::Extra> {
40 if let Extra::IoUring(extra) = &self.0 {
41 Some(extra)
42 } else {
43 None
44 }
45 }
46
47 pub(in crate::sys) fn try_as_iour_mut(&mut self) -> Option<&mut iour::Extra> {
48 if let Extra::IoUring(extra) = &mut self.0 {
49 Some(extra)
50 } else {
51 None
52 }
53 }
54
55 pub(in crate::sys) fn try_as_poll(&self) -> Option<&poll::Extra> {
56 if let Extra::Poll(extra) = &self.0 {
57 Some(extra)
58 } else {
59 None
60 }
61 }
62
63 pub(in crate::sys) fn try_as_poll_mut(&mut self) -> Option<&mut poll::Extra> {
64 if let Extra::Poll(extra) = &mut self.0 {
65 Some(extra)
66 } else {
67 None
68 }
69 }
70}
71
72pub trait OpCode: PollOpCode + IourOpCode {}
76
77impl<T: PollOpCode + IourOpCode + ?Sized> OpCode for T {}
78
79#[allow(clippy::large_enum_variant)]
80enum FuseDriver {
81 Poll(poll::Driver),
82 IoUring(iour::Driver),
83}
84
85pub(crate) struct Driver {
87 fuse: FuseDriver,
88}
89
90impl Driver {
91 pub fn new(builder: &ProactorBuilder) -> io::Result<Self> {
93 let (ty, fallback) = match &builder.driver_type {
94 Some(t) => (*t, false),
95 None => (DriverType::suggest(), true),
96 };
97 match ty {
98 DriverType::Poll => Ok(Self {
99 fuse: FuseDriver::Poll(poll::Driver::new(builder)?),
100 }),
101 DriverType::IoUring => match iour::Driver::new(builder) {
102 Ok(driver) => Ok(Self {
103 fuse: FuseDriver::IoUring(driver),
104 }),
105 Err(_e) if fallback => {
107 warn!("Fail to create io-uring driver: {_e:?}, fallback to polling driver.");
108 Ok(Self {
109 fuse: FuseDriver::Poll(poll::Driver::new(builder)?),
110 })
111 }
112 Err(e) => Err(e),
113 },
114 _ => unreachable!("Fuse driver will only be enabled on linux"),
115 }
116 }
117
118 #[allow(dead_code)]
119 pub fn as_iour(&self) -> Option<&iour::Driver> {
120 if let FuseDriver::IoUring(driver) = &self.fuse {
121 Some(driver)
122 } else {
123 None
124 }
125 }
126
127 pub fn driver_type(&self) -> DriverType {
128 match &self.fuse {
129 FuseDriver::Poll(driver) => driver.driver_type(),
130 FuseDriver::IoUring(driver) => driver.driver_type(),
131 }
132 }
133
134 pub fn default_extra(&self) -> Extra {
135 match &self.fuse {
136 FuseDriver::Poll(driver) => Extra::Poll(driver.default_extra()),
137 FuseDriver::IoUring(driver) => Extra::IoUring(driver.default_extra()),
138 }
139 }
140
141 pub fn attach(&mut self, fd: RawFd) -> io::Result<()> {
142 match &mut self.fuse {
143 FuseDriver::Poll(driver) => driver.attach(fd),
144 FuseDriver::IoUring(driver) => driver.attach(fd),
145 }
146 }
147
148 pub fn cancel<T>(&mut self, key: Key<T>) {
149 match &mut self.fuse {
150 FuseDriver::Poll(driver) => driver.cancel(key),
151 FuseDriver::IoUring(driver) => driver.cancel(key),
152 }
153 }
154
155 pub fn push(&mut self, op: ErasedKey) -> Poll<io::Result<usize>> {
156 match &mut self.fuse {
157 FuseDriver::Poll(driver) => driver.push(op),
158 FuseDriver::IoUring(driver) => driver.push(op),
159 }
160 }
161
162 pub fn poll(&mut self, timeout: Option<Duration>) -> io::Result<()> {
163 match &mut self.fuse {
164 FuseDriver::Poll(driver) => driver.poll(timeout),
165 FuseDriver::IoUring(driver) => driver.poll(timeout),
166 }
167 }
168
169 pub fn waker(&self) -> Waker {
170 match &self.fuse {
171 FuseDriver::Poll(driver) => driver.waker(),
172 FuseDriver::IoUring(driver) => driver.waker(),
173 }
174 }
175
176 pub fn create_buffer_pool(
177 &mut self,
178 buffer_len: u16,
179 buffer_size: usize,
180 ) -> io::Result<BufferPool> {
181 match &mut self.fuse {
182 FuseDriver::IoUring(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
183 FuseDriver::Poll(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
184 }
185 }
186
187 pub unsafe fn release_buffer_pool(&mut self, buffer_pool: BufferPool) -> io::Result<()> {
191 unsafe {
192 match &mut self.fuse {
193 FuseDriver::Poll(driver) => driver.release_buffer_pool(buffer_pool),
194 FuseDriver::IoUring(driver) => driver.release_buffer_pool(buffer_pool),
195 }
196 }
197 }
198}
199
200impl AsRawFd for Driver {
201 fn as_raw_fd(&self) -> RawFd {
202 match &self.fuse {
203 FuseDriver::Poll(driver) => driver.as_raw_fd(),
204 FuseDriver::IoUring(driver) => driver.as_raw_fd(),
205 }
206 }
207}