1pub const DEFAULT_BUF_SIZE: usize = 4096;
11
12pub const DEFAULT_POOL_SIZE: usize = 1024;
14
15pub struct BufferPool {
17 slots: Box<[Box<[u8; DEFAULT_BUF_SIZE]>]>,
19 free: Vec<u32>,
21 buf_size: usize,
23}
24
25impl BufferPool {
26 #[must_use]
32 pub fn new(capacity: usize, buf_size: usize) -> Option<Self> {
33 if buf_size != DEFAULT_BUF_SIZE {
34 return None; }
36 let mut slots = Vec::with_capacity(capacity);
37 let mut free = Vec::with_capacity(capacity);
38 for i in 0..capacity {
39 slots.push(vec![0u8; buf_size].into_boxed_slice().try_into().ok()?);
40 free.push(i as u32);
41 }
42 Some(Self {
43 slots: slots.into_boxed_slice(),
44 free,
45 buf_size,
46 })
47 }
48
49 #[must_use]
51 #[inline]
52 pub fn buf_size(&self) -> usize {
53 self.buf_size
54 }
55
56 #[must_use]
58 #[inline]
59 pub fn capacity(&self) -> usize {
60 self.slots.len()
61 }
62
63 #[must_use]
65 #[inline]
66 pub fn free_slots(&self) -> usize {
67 self.free.len()
68 }
69
70 #[inline]
73 pub fn take(&mut self) -> Option<u32> {
74 self.free.pop()
75 }
76
77 #[inline]
79 pub fn release(&mut self, slot: u32) {
80 debug_assert!((slot as usize) < self.slots.len(), "slot out of range");
81 self.free.push(slot);
82 }
83
84 #[must_use]
86 #[inline]
87 pub fn slot(&self, slot: u32) -> &[u8; DEFAULT_BUF_SIZE] {
88 &self.slots[slot as usize]
89 }
90
91 #[inline]
93 pub fn slot_mut(&mut self, slot: u32) -> &mut [u8; DEFAULT_BUF_SIZE] {
94 &mut self.slots[slot as usize]
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn take_release() {
104 let mut pool = BufferPool::new(4, DEFAULT_BUF_SIZE).expect("default size");
105 assert_eq!(pool.free_slots(), 4);
106 let a = pool.take().expect("slot");
107 let b = pool.take().expect("slot");
108 assert_eq!(pool.free_slots(), 2);
109 pool.release(a);
110 assert_eq!(pool.free_slots(), 3);
111 let _c = pool.take();
112 let d = pool.take();
113 assert!(d.is_some());
114 pool.release(b); }
116
117 #[test]
118 fn exhaustion() {
119 let mut pool = BufferPool::new(2, DEFAULT_BUF_SIZE).expect("default size");
120 let _ = pool.take();
121 let _ = pool.take();
122 assert!(pool.take().is_none(), "pool exhausted");
123 }
124}