1use std::time::Duration;
2
3use context::{mono_thread, multi_thread};
4pub mod context;
5
6struct 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
19pub 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 pub fn new() -> Self {
41 Self::default()
42 }
43
44 pub fn set_max_number_of_buffer(&mut self, number: usize) -> &mut Self {
46 self.max_nb_buffer = number;
47 self
48 }
49 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 pub fn set_buffer_size(&mut self, number: usize) -> &mut Self {
59 self.buffer_size = number;
60 self
61 }
62 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 pub fn build_mono_thread(&self) -> mono_thread::BufferPool {
70 mono_thread::BufferPool::from_builder(self)
71 }
72 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 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}