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