Skip to main content

compio_driver/buffer_pool/
fallback.rs

1//! The fallback buffer pool. It is backed by a [`VecDeque`] of [`Vec<u8>`].
2//! An [`OwnedBuffer`] is selected when the op is created. It keeps a strong
3//! reference to the buffer pool. The [`BorrowedBuffer`] is created after the op
4//! returns successfully.
5
6use std::{
7    borrow::{Borrow, BorrowMut},
8    cell::RefCell,
9    collections::VecDeque,
10    fmt::{Debug, Formatter},
11    io,
12    mem::ManuallyDrop,
13    ops::{Deref, DerefMut},
14    rc::Rc,
15};
16
17use compio_buf::{IntoInner, IoBuf, IoBufMut, SetLen, Slice};
18#[cfg(not(fusion))]
19pub use {BufferPool as FallbackBufferPool, OwnedBuffer as FallbackOwnedBuffer};
20
21struct BufferPoolInner {
22    buffers: RefCell<VecDeque<Vec<u8>>>,
23}
24
25impl BufferPoolInner {
26    pub(crate) fn add_buffer(&self, mut buffer: Vec<u8>) {
27        buffer.clear();
28        self.buffers.borrow_mut().push_back(buffer)
29    }
30}
31
32/// Buffer pool
33///
34/// A buffer pool to allow user no need to specify a specific buffer to do the
35/// IO operation
36pub struct BufferPool {
37    inner: Rc<BufferPoolInner>,
38}
39
40impl Debug for BufferPool {
41    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42        f.debug_struct("BufferPool").finish_non_exhaustive()
43    }
44}
45
46impl BufferPool {
47    pub(crate) fn new(buffer_len: u16, buffer_size: usize) -> Self {
48        // To match the behavior of io-uring, extend the number of buffers.
49        let buffers = (0..buffer_len.next_power_of_two())
50            .map(|_| Vec::with_capacity(buffer_size))
51            .collect();
52
53        Self {
54            inner: Rc::new(BufferPoolInner {
55                buffers: RefCell::new(buffers),
56            }),
57        }
58    }
59
60    /// Select an [`OwnedBuffer`] when the op creates.
61    #[doc(hidden)]
62    pub fn get_buffer(&self, len: usize) -> io::Result<OwnedBuffer> {
63        let buffer = self
64            .inner
65            .buffers
66            .borrow_mut()
67            .pop_front()
68            .ok_or_else(|| io::Error::other("buffer ring has no available buffer"))?;
69        let len = if len == 0 {
70            buffer.capacity()
71        } else {
72            buffer.capacity().min(len)
73        };
74        Ok(OwnedBuffer::new(buffer.slice(..len), self.inner.clone()))
75    }
76
77    /// Return the buffer to the pool.
78    pub(crate) fn add_buffer(&self, buffer: Vec<u8>) {
79        self.inner.add_buffer(buffer);
80    }
81
82    /// ## Safety
83    /// * `len` should be valid.
84    #[doc(hidden)]
85    pub unsafe fn create_proxy(&self, mut slice: OwnedBuffer, len: usize) -> BorrowedBuffer<'_> {
86        unsafe {
87            slice.advance_to(len);
88        }
89        BorrowedBuffer::new(slice.into_inner(), self)
90    }
91}
92
93#[doc(hidden)]
94pub struct OwnedBuffer {
95    buffer: ManuallyDrop<Slice<Vec<u8>>>,
96    pool: ManuallyDrop<Rc<BufferPoolInner>>,
97}
98
99impl OwnedBuffer {
100    fn new(buffer: Slice<Vec<u8>>, pool: Rc<BufferPoolInner>) -> Self {
101        Self {
102            buffer: ManuallyDrop::new(buffer),
103            pool: ManuallyDrop::new(pool),
104        }
105    }
106}
107
108impl IoBuf for OwnedBuffer {
109    fn as_init(&self) -> &[u8] {
110        self.buffer.as_init()
111    }
112}
113
114impl IoBufMut for OwnedBuffer {
115    fn as_uninit(&mut self) -> &mut [std::mem::MaybeUninit<u8>] {
116        self.buffer.as_uninit()
117    }
118}
119
120impl SetLen for OwnedBuffer {
121    unsafe fn set_len(&mut self, len: usize) {
122        unsafe { self.buffer.set_len(len) }
123    }
124}
125
126impl Drop for OwnedBuffer {
127    fn drop(&mut self) {
128        // SAFETY: `take` is called only once here.
129        self.pool
130            .add_buffer(unsafe { ManuallyDrop::take(&mut self.buffer) }.into_inner());
131        // SAFETY: `drop` is called only once here.
132        unsafe { ManuallyDrop::drop(&mut self.pool) };
133    }
134}
135
136impl IntoInner for OwnedBuffer {
137    type Inner = Slice<Vec<u8>>;
138
139    fn into_inner(mut self) -> Self::Inner {
140        // SAFETY: `self` is forgotten in this method.
141        let buffer = unsafe { ManuallyDrop::take(&mut self.buffer) };
142        // The buffer is taken, we only need to drop the Rc.
143        // SAFETY: `self` is forgotten in this method.
144        unsafe { ManuallyDrop::drop(&mut self.pool) };
145        std::mem::forget(self);
146        buffer
147    }
148}
149
150/// Buffer borrowed from buffer pool
151///
152/// When IO operation finish, user will obtain a `BorrowedBuffer` to access the
153/// filled data
154pub struct BorrowedBuffer<'a> {
155    buffer: ManuallyDrop<Slice<Vec<u8>>>,
156    pool: &'a BufferPool,
157}
158
159impl<'a> BorrowedBuffer<'a> {
160    pub(crate) fn new(buffer: Slice<Vec<u8>>, pool: &'a BufferPool) -> Self {
161        Self {
162            buffer: ManuallyDrop::new(buffer),
163            pool,
164        }
165    }
166}
167
168impl Debug for BorrowedBuffer<'_> {
169    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
170        f.debug_struct("BorrowedBuffer").finish_non_exhaustive()
171    }
172}
173
174impl Drop for BorrowedBuffer<'_> {
175    fn drop(&mut self) {
176        // SAFETY: `take` is called only once here.
177        let buffer = unsafe { ManuallyDrop::take(&mut self.buffer) };
178        self.pool.add_buffer(buffer.into_inner());
179    }
180}
181
182impl Deref for BorrowedBuffer<'_> {
183    type Target = [u8];
184
185    fn deref(&self) -> &Self::Target {
186        self.buffer.deref()
187    }
188}
189
190impl DerefMut for BorrowedBuffer<'_> {
191    fn deref_mut(&mut self) -> &mut Self::Target {
192        self.buffer.deref_mut()
193    }
194}
195
196impl AsRef<[u8]> for BorrowedBuffer<'_> {
197    fn as_ref(&self) -> &[u8] {
198        self.deref()
199    }
200}
201
202impl AsMut<[u8]> for BorrowedBuffer<'_> {
203    fn as_mut(&mut self) -> &mut [u8] {
204        self.deref_mut()
205    }
206}
207
208impl Borrow<[u8]> for BorrowedBuffer<'_> {
209    fn borrow(&self) -> &[u8] {
210        self.deref()
211    }
212}
213
214impl BorrowMut<[u8]> for BorrowedBuffer<'_> {
215    fn borrow_mut(&mut self) -> &mut [u8] {
216        self.deref_mut()
217    }
218}