safa_buffer_pool/
lib.rs

1use std::time::Duration;
2
3use context::{mono_thread, multi_thread};
4pub mod context;
5
6///Unique BufferPool
7struct BufferPool {
8    total_nb_buffer: usize,
9
10    max_nb_buffer: usize,
11    min_nb_buffer: usize,
12    buffer_size: usize,
13
14    min_available_nb_buffer: usize,
15
16    all_available_buffer: Vec<Box<[u8]>>,
17}
18
19///A builder for BufferPool
20pub struct BufferPoolBuilder {
21    max_nb_buffer: usize,
22    min_nb_buffer: usize,
23    buffer_size: usize,
24    over_buffer_lifetime_opt: Option<Duration>,
25}
26
27impl Default for BufferPoolBuilder {
28    fn default() -> Self {
29        Self {
30            max_nb_buffer: 1024,
31            min_nb_buffer: 1024,
32            buffer_size: 10240,
33            over_buffer_lifetime_opt: None,
34        }
35    }
36}
37
38impl BufferPoolBuilder {
39    ///Create a new BufferPoolBuilder
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    ///Set the maximum of buffer in the pool
45    pub fn set_max_number_of_buffer(&mut self, number: usize) -> &mut Self {
46        self.max_nb_buffer = number;
47        self
48    }
49    ///Set the minimum of buffer in the pool
50    pub fn set_min_number_of_buffer(&mut self, number: usize) -> &mut Self {
51        self.min_nb_buffer = number;
52        if self.max_nb_buffer < number {
53            self.max_nb_buffer = number;
54        }
55        self
56    }
57    ///Set the size of each buffer in the pool
58    pub fn set_buffer_size(&mut self, number: usize) -> &mut Self {
59        self.buffer_size = number;
60        self
61    }
62    ///Set the maximum inactivity time for excess buffers before being deleted
63    pub fn set_over_buffer_lifetime(&mut self, new_duration: Duration) -> &mut Self {
64        self.over_buffer_lifetime_opt = Some(new_duration);
65        self
66    }
67
68    ///Build a mono thread pool from this builder
69    pub fn build_mono_thread(&self) -> mono_thread::BufferPool {
70        mono_thread::BufferPool::from_builder(self)
71    }
72    ///Build a multi thread pool from this builder
73    pub fn build_multi_thread(&self) -> multi_thread::BufferPool {
74        multi_thread::BufferPool::from_builder(self)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use std::time::Duration;
81
82    use tokio::{task, time::sleep};
83
84    use crate::BufferPoolBuilder;
85
86    #[tokio::test]
87    async fn basic_test() {
88        let pool = BufferPoolBuilder::new().build_multi_thread();
89
90        let pool_cl = pool.clone();
91        let a = tokio::spawn(async move {
92            for _ in 0..10000 {
93                println!("A: try to get a new buffer");
94                let new_buffer_opt = pool_cl.get().await;
95                if new_buffer_opt.is_none() {
96                    println!("A: buffer no available");
97                    break;
98                }
99                let mut new_buffer = new_buffer_opt.unwrap();
100                new_buffer[0] = 0x01;
101                new_buffer[1] = 0x02;
102                new_buffer[2] = 0x03;
103                println!("A: free a buffer");
104            }
105        });
106
107        let pool_cl2 = pool.clone();
108        let b = tokio::spawn(async move {
109            for _ in 0..10000 {
110                println!("B: try to get a new buffer");
111                let new_buffer_opt = pool_cl2.get().await;
112                if new_buffer_opt.is_none() {
113                    println!("B: buffer no available");
114                    break;
115                }
116                let mut new_buffer = new_buffer_opt.unwrap();
117                new_buffer[0] = 0x01;
118                new_buffer[1] = 0x02;
119                new_buffer[2] = 0x03;
120                println!("B: free a buffer");
121            }
122        });
123
124        let _ = a.await;
125        let _ = b.await;
126    }
127
128    #[test]
129    fn big_pool() {
130        //10Go Pool (10240 buffer of 1Mo)
131        let _pool = BufferPoolBuilder::new()
132            .set_buffer_size(1024 * 1024)
133            .set_min_number_of_buffer(10240)
134            .build_mono_thread();
135    }
136
137    #[tokio::test]
138    async fn over_buffer() {
139        let pool = BufferPoolBuilder::new()
140            .set_buffer_size(1024 * 1024)
141            .set_min_number_of_buffer(100)
142            .set_max_number_of_buffer(200)
143            .set_over_buffer_lifetime(Duration::from_secs(2))
144            .build_multi_thread();
145
146        for _ in 0..150 {
147            let pool_cl = pool.clone();
148            task::spawn(async move {
149                let _buffer = pool_cl.get().await;
150                sleep(Duration::from_secs(3)).await;
151            });
152        }
153
154        sleep(Duration::from_secs(4)).await;
155
156        for _ in 0..120 {
157            let pool_cl = pool.clone();
158            task::spawn(async move {
159                let _buffer = pool_cl.get().await;
160                sleep(Duration::from_secs(3)).await;
161            });
162        }
163
164        sleep(Duration::from_secs(5)).await;
165    }
166}