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::{AsRawFd, 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::{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
96impl AsRawFd for Driver {
97    fn as_raw_fd(&self) -> RawFd {
98        match &self.fuse {
99            FuseDriver::Poll(driver) => driver.as_raw_fd(),
100            FuseDriver::IoUring(driver) => driver.as_raw_fd(),
101        }
102    }
103}
104
105enum FuseNotifyHandle {
106    Poll(poll::NotifyHandle),
107    IoUring(iour::NotifyHandle),
108}
109
110/// A notify handle to the inner driver.
111pub struct NotifyHandle {
112    fuse: FuseNotifyHandle,
113}
114
115impl NotifyHandle {
116    fn from_fuse(fuse: FuseNotifyHandle) -> Self {
117        Self { fuse }
118    }
119
120    /// Notify the inner driver.
121    pub fn notify(&self) -> io::Result<()> {
122        match &self.fuse {
123            FuseNotifyHandle::Poll(handle) => handle.notify(),
124            FuseNotifyHandle::IoUring(handle) => handle.notify(),
125        }
126    }
127}