compio_driver/fusion/
mod.rs

1#[path = "../poll/mod.rs"]
2mod poll;
3
4#[path = "../iour/mod.rs"]
5mod iour;
6
7pub(crate) mod op;
8
9#[cfg_attr(all(doc, docsrs), doc(cfg(all())))]
10pub use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
11use std::{io, task::Poll, time::Duration};
12
13pub use iour::{OpCode as IourOpCode, OpEntry};
14pub(crate) use iour::{sockaddr_storage, socklen_t};
15pub use poll::{Decision, OpCode as PollOpCode, OpType};
16
17pub use crate::driver_type::DriverType; // Re-export so current user won't be broken
18use crate::{BufferPool, Key, ProactorBuilder};
19
20/// Fused [`OpCode`]
21///
22/// This trait encapsulates both operation for `io-uring` and `polling`
23pub trait OpCode: PollOpCode + IourOpCode {}
24
25impl<T: PollOpCode + IourOpCode + ?Sized> OpCode for T {}
26
27#[allow(clippy::large_enum_variant)]
28enum FuseDriver {
29    Poll(poll::Driver),
30    IoUring(iour::Driver),
31}
32
33/// Low-level fusion driver.
34pub(crate) struct Driver {
35    fuse: FuseDriver,
36}
37
38impl Driver {
39    /// Create a new fusion driver with given number of entries
40    pub fn new(builder: &ProactorBuilder) -> io::Result<Self> {
41        match DriverType::current() {
42            DriverType::Poll => Ok(Self {
43                fuse: FuseDriver::Poll(poll::Driver::new(builder)?),
44            }),
45            DriverType::IoUring => Ok(Self {
46                fuse: FuseDriver::IoUring(iour::Driver::new(builder)?),
47            }),
48            _ => unreachable!("Fuse driver will only be enabled on linux"),
49        }
50    }
51
52    pub fn create_op<T: OpCode + 'static>(&self, op: T) -> Key<T> {
53        match &self.fuse {
54            FuseDriver::Poll(driver) => driver.create_op(op),
55            FuseDriver::IoUring(driver) => driver.create_op(op),
56        }
57    }
58
59    pub fn attach(&mut self, fd: RawFd) -> io::Result<()> {
60        match &mut self.fuse {
61            FuseDriver::Poll(driver) => driver.attach(fd),
62            FuseDriver::IoUring(driver) => driver.attach(fd),
63        }
64    }
65
66    pub fn cancel(&mut self, op: &mut Key<dyn OpCode>) {
67        match &mut self.fuse {
68            FuseDriver::Poll(driver) => driver.cancel(op),
69            FuseDriver::IoUring(driver) => driver.cancel(op),
70        }
71    }
72
73    pub fn push(&mut self, op: &mut Key<dyn OpCode>) -> Poll<io::Result<usize>> {
74        match &mut self.fuse {
75            FuseDriver::Poll(driver) => driver.push(op),
76            FuseDriver::IoUring(driver) => driver.push(op),
77        }
78    }
79
80    pub unsafe fn poll(&mut self, timeout: Option<Duration>) -> io::Result<()> {
81        match &mut self.fuse {
82            FuseDriver::Poll(driver) => driver.poll(timeout),
83            FuseDriver::IoUring(driver) => driver.poll(timeout),
84        }
85    }
86
87    pub fn handle(&self) -> NotifyHandle {
88        let fuse = match &self.fuse {
89            FuseDriver::Poll(driver) => FuseNotifyHandle::Poll(driver.handle()),
90            FuseDriver::IoUring(driver) => FuseNotifyHandle::IoUring(driver.handle()),
91        };
92        NotifyHandle::from_fuse(fuse)
93    }
94
95    pub fn create_buffer_pool(
96        &mut self,
97        buffer_len: u16,
98        buffer_size: usize,
99    ) -> io::Result<BufferPool> {
100        match &mut self.fuse {
101            FuseDriver::IoUring(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
102            FuseDriver::Poll(driver) => Ok(driver.create_buffer_pool(buffer_len, buffer_size)?),
103        }
104    }
105
106    /// # Safety
107    ///
108    /// caller must make sure release the buffer pool with correct driver
109    pub unsafe fn release_buffer_pool(&mut self, buffer_pool: BufferPool) -> io::Result<()> {
110        match &mut self.fuse {
111            FuseDriver::Poll(driver) => driver.release_buffer_pool(buffer_pool),
112            FuseDriver::IoUring(driver) => driver.release_buffer_pool(buffer_pool),
113        }
114    }
115}
116
117impl AsRawFd for Driver {
118    fn as_raw_fd(&self) -> RawFd {
119        match &self.fuse {
120            FuseDriver::Poll(driver) => driver.as_raw_fd(),
121            FuseDriver::IoUring(driver) => driver.as_raw_fd(),
122        }
123    }
124}
125
126enum FuseNotifyHandle {
127    Poll(poll::NotifyHandle),
128    IoUring(iour::NotifyHandle),
129}
130
131/// A notify handle to the inner driver.
132pub struct NotifyHandle {
133    fuse: FuseNotifyHandle,
134}
135
136impl NotifyHandle {
137    fn from_fuse(fuse: FuseNotifyHandle) -> Self {
138        Self { fuse }
139    }
140
141    /// Notify the inner driver.
142    pub fn notify(&self) -> io::Result<()> {
143        match &self.fuse {
144            FuseNotifyHandle::Poll(handle) => handle.notify(),
145            FuseNotifyHandle::IoUring(handle) => handle.notify(),
146        }
147    }
148}