safa_buffer_pool/context/
mono_thread.rs1use std::{
2 cell::RefCell,
3 cmp::min,
4 mem::ManuallyDrop,
5 ops::{Deref, DerefMut, Index, IndexMut},
6 rc::Rc,
7};
8
9use crate::{BufferPool as RawBufferPool, BufferPoolBuilder};
10
11#[derive(Clone)]
13pub struct BufferPool {
14 inner_rc: Rc<RefCell<RawBufferPool>>,
15}
16
17impl BufferPool {
18 pub fn get(&self) -> Option<BufferGuard> {
22 let mut pool = self.inner_rc.borrow_mut();
23
24 if let Some(new_buffer) = pool.all_available_buffer.pop() {
25 let nb_available_buffer = pool.all_available_buffer.len();
26 if nb_available_buffer < pool.min_available_nb_buffer {
27 pool.min_available_nb_buffer = nb_available_buffer;
28 }
29
30 return Some(BufferGuard {
31 pool: self.clone(),
32 buffer: ManuallyDrop::new(new_buffer),
33 });
34 }
35
36 if pool.total_nb_buffer == pool.max_nb_buffer {
37 return None;
38 }
39 pool.total_nb_buffer += 1;
40
41 let buffer_size = pool.buffer_size;
42
43 Some(BufferGuard {
44 pool: self.clone(),
45 buffer: ManuallyDrop::new(vec![0u8; buffer_size].into_boxed_slice()),
46 })
47 }
48
49 pub fn reduce_allocated_buffer(&mut self) {
51 let mut pool = self.inner_rc.borrow_mut();
52
53 let total_droppable_buffer = pool.total_nb_buffer - pool.min_nb_buffer;
54 let nb_drop_buffer = min(total_droppable_buffer, pool.min_available_nb_buffer);
55
56 let nb_buffer_to_keep = pool.all_available_buffer.len() - nb_drop_buffer;
57 pool.total_nb_buffer -= nb_drop_buffer;
58 pool.all_available_buffer.truncate(nb_buffer_to_keep);
59
60 pool.min_available_nb_buffer = pool.all_available_buffer.len();
61 }
62
63 pub fn from_builder(builder: &BufferPoolBuilder) -> BufferPool {
65 let mut all_buffer = Vec::with_capacity(builder.max_nb_buffer);
66
67 for _ in 0..builder.min_nb_buffer {
68 all_buffer.push(vec![0u8; builder.buffer_size].into_boxed_slice());
69 }
70
71 BufferPool {
72 inner_rc: Rc::new(RefCell::new(RawBufferPool {
73 total_nb_buffer: builder.min_nb_buffer,
74
75 max_nb_buffer: builder.max_nb_buffer,
76 min_nb_buffer: builder.min_nb_buffer,
77 buffer_size: builder.buffer_size,
78
79 min_available_nb_buffer: builder.min_nb_buffer,
80
81 all_available_buffer: all_buffer,
82 })),
83 }
84 }
85}
86
87pub struct BufferGuard {
89 pool: BufferPool,
90 buffer: ManuallyDrop<Box<[u8]>>,
91}
92
93impl Drop for BufferGuard {
94 fn drop(&mut self) {
95 let mut pool = self.pool.inner_rc.borrow_mut();
96 let buffer = unsafe { ManuallyDrop::take(&mut self.buffer) };
97 pool.all_available_buffer.push(buffer);
98 }
99}
100
101impl Deref for BufferGuard {
102 type Target = [u8];
103 fn deref(&self) -> &Self::Target {
104 &self.buffer
105 }
106}
107
108impl DerefMut for BufferGuard {
109 fn deref_mut(&mut self) -> &mut Self::Target {
110 &mut self.buffer
111 }
112}
113
114impl Index<usize> for BufferGuard {
115 type Output = u8;
116 fn index(&self, idx: usize) -> &Self::Output {
117 &self.buffer[idx]
118 }
119}
120impl IndexMut<usize> for BufferGuard {
121 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
122 &mut self.buffer[idx]
123 }
124}