1use std::sync::Arc;
2
3use tokio::sync::Mutex;
4
5#[derive(Clone, Default)]
7pub struct MultiThreadBufferPool {
8 inner_arc: Arc<Mutex<BufferPool>>,
9}
10
11impl MultiThreadBufferPool {
12 pub async fn get(&self) -> Option<BufferGuard> {
13 let mut pool = self.inner_arc.lock().await;
14 if let Some(new_buffer) = pool.all_available_buffer.pop() {
15 return Some(BufferGuard {
16 pool: self.clone(),
17 buffer: new_buffer,
18 });
19 }
20
21 if pool.total_nb_buffer == pool.max_nb_buffer {
22 return None;
23 }
24 pool.total_nb_buffer += 1;
25
26 let buffer_size = pool.buffer_size;
27
28 drop(pool); Some(BufferGuard {
31 pool: self.clone(),
32 buffer: vec![0u8; buffer_size].into_boxed_slice(),
33 })
34 }
35}
36
37#[derive(Default)]
39struct BufferPool {
40 total_nb_buffer: usize,
41 max_nb_buffer: usize,
42 min_nb_buffer: usize,
43 buffer_size: usize,
44 all_available_buffer: Vec<Box<[u8]>>,
45}
46
47pub struct BufferPoolBuilder {
48 max_nb_buffer: usize,
49 min_nb_buffer: usize,
50 buffer_size: usize,
51}
52
53impl Default for BufferPoolBuilder {
54 fn default() -> Self {
55 Self {
56 max_nb_buffer: 1024,
57 min_nb_buffer: 1024,
58 buffer_size: 10240,
59 }
60 }
61}
62
63impl BufferPoolBuilder {
64 pub fn new() -> Self {
65 Self::default()
66 }
67
68 pub fn set_max_number_of_buffer(&mut self, number: usize) {
69 self.max_nb_buffer = number;
70 }
71 pub fn set_min_number_of_buffer(&mut self, number: usize) {
72 self.min_nb_buffer = number;
73 }
74 pub fn set_buffer_size(&mut self, number: usize) {
75 self.buffer_size = number;
76 }
77
78 pub fn build_multi_thread_buffer_pool(&self) -> MultiThreadBufferPool {
79 let mut all_buffer = Vec::with_capacity(self.max_nb_buffer);
80
81 for _ in 0..self.min_nb_buffer {
82 all_buffer.push(vec![0u8; self.buffer_size].into_boxed_slice());
83 }
84
85 MultiThreadBufferPool {
86 inner_arc: Arc::new(Mutex::new(BufferPool {
87 total_nb_buffer: self.min_nb_buffer,
88 max_nb_buffer: self.max_nb_buffer,
89 min_nb_buffer: self.min_nb_buffer,
90 buffer_size: self.buffer_size,
91 all_available_buffer: all_buffer,
92 })),
93 }
94 }
95}
96
97pub struct BufferGuard {
98 pool: MultiThreadBufferPool,
99 buffer: Box<[u8]>,
100}
101
102impl Drop for BufferGuard {
103 fn drop(&mut self) {
104 let pool = std::mem::take(&mut self.pool);
105 let buffer = std::mem::take(&mut self.buffer);
106
107 tokio::spawn(async move {
108 let mut pool = pool.inner_arc.lock().await;
109 pool.all_available_buffer.push(buffer);
110 });
111 }
112}