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