network_protocol/utils/
buffer_pool.rs1use std::sync::{Arc, Mutex};
22
23const MAX_POOLED_BUFFER_SIZE: usize = 4096;
25
26const DEFAULT_BUFFER_CAPACITY: usize = 1024;
28
29pub struct PooledBuffer {
31 buffer: Vec<u8>,
32 pool: Arc<Mutex<Vec<Vec<u8>>>>,
33}
34
35impl PooledBuffer {
36 #[allow(clippy::should_implement_trait)]
38 pub fn as_mut(&mut self) -> &mut Vec<u8> {
39 &mut self.buffer
40 }
41
42 #[allow(clippy::should_implement_trait)]
44 pub fn as_ref(&self) -> &[u8] {
45 &self.buffer
46 }
47
48 pub fn into_inner(mut self) -> Vec<u8> {
50 self.buffer.clear();
52 std::mem::take(&mut self.buffer)
53 }
54}
55
56impl Drop for PooledBuffer {
57 fn drop(&mut self) {
58 if self.buffer.capacity() <= MAX_POOLED_BUFFER_SIZE {
60 self.buffer.clear(); if let Ok(mut pool) = self.pool.lock() {
62 pool.push(std::mem::take(&mut self.buffer));
63 }
64 }
65 }
67}
68
69impl std::ops::Deref for PooledBuffer {
70 type Target = Vec<u8>;
71
72 fn deref(&self) -> &Self::Target {
73 &self.buffer
74 }
75}
76
77impl std::ops::DerefMut for PooledBuffer {
78 fn deref_mut(&mut self) -> &mut Self::Target {
79 &mut self.buffer
80 }
81}
82
83pub struct BufferPool {
85 pool: Arc<Mutex<Vec<Vec<u8>>>>,
86 initial_capacity: usize,
87}
88
89impl BufferPool {
90 pub fn new(pool_size: usize) -> Self {
92 let mut pool = Vec::with_capacity(pool_size);
93
94 for _ in 0..pool_size {
96 pool.push(Vec::with_capacity(DEFAULT_BUFFER_CAPACITY));
97 }
98
99 Self {
100 pool: Arc::new(Mutex::new(pool)),
101 initial_capacity: DEFAULT_BUFFER_CAPACITY,
102 }
103 }
104
105 pub fn acquire(&self) -> PooledBuffer {
107 let buffer = if let Ok(mut pool) = self.pool.lock() {
108 pool.pop()
109 .unwrap_or_else(|| Vec::with_capacity(self.initial_capacity))
110 } else {
111 Vec::with_capacity(self.initial_capacity)
112 };
113
114 PooledBuffer {
115 buffer,
116 pool: self.pool.clone(),
117 }
118 }
119
120 pub fn available(&self) -> usize {
122 self.pool.lock().map(|p| p.len()).unwrap_or(0)
123 }
124}
125
126impl Default for BufferPool {
127 fn default() -> Self {
128 Self::new(50) }
130}
131
132impl Clone for BufferPool {
133 fn clone(&self) -> Self {
134 Self {
135 pool: self.pool.clone(),
136 initial_capacity: self.initial_capacity,
137 }
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn test_buffer_pool_basic() {
147 let pool = BufferPool::new(10);
148 assert_eq!(pool.available(), 10);
149
150 let mut buf = pool.acquire();
151 assert_eq!(pool.available(), 9);
152
153 buf.push(42);
154 assert_eq!(buf[0], 42);
155
156 drop(buf);
157 assert_eq!(pool.available(), 10);
158 }
159
160 #[test]
161 fn test_buffer_pool_reuse() {
162 let pool = BufferPool::new(1);
163
164 {
165 let mut buf1 = pool.acquire();
166 buf1.extend_from_slice(b"test");
167 assert_eq!(buf1.len(), 4);
168 }
169
170 let buf2 = pool.acquire();
172 assert_eq!(buf2.len(), 0);
173 assert!(buf2.capacity() >= 4);
174 }
175
176 #[test]
177 fn test_buffer_pool_empty() {
178 let pool = BufferPool::new(1);
179 let _buf1 = pool.acquire();
180 let _buf2 = pool.acquire(); assert_eq!(pool.available(), 0);
184 }
185
186 #[test]
187 fn test_buffer_size_limit() {
188 let pool = BufferPool::new(1);
189
190 {
191 let mut buf = pool.acquire();
192 buf.reserve(MAX_POOLED_BUFFER_SIZE + 1);
194 buf.extend_from_slice(&vec![0u8; MAX_POOLED_BUFFER_SIZE + 1]);
195 }
196
197 assert_eq!(pool.available(), 0);
199 }
200}