safa_buffer_pool/context/
mono_thread.rs

1use 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///BufferPool for Mono-thread context
12#[derive(Clone)]
13pub struct BufferPool {
14    inner_rc: Rc<RefCell<RawBufferPool>>,
15}
16
17impl BufferPool {
18    ///Get a new buffer from the pool
19    /// 
20    ///Return None if none buffer available
21    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    ///Optimize the number of buffer(deleted excess buffer) in the pool
50    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    ///Like BufferPoolBuilder.build_mono_thread()
64    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
87///A buffer guard for auto-drop of buffer, useable like a buffer
88pub 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}