use std::sync::Mutex;
use std::sync::atomic::{AtomicUsize, Ordering};
use super::MBuf;
pub struct MPool {
free_list: Mutex<Vec<MBuf>>,
allocated_count: AtomicUsize,
capacity: usize,
}
impl MPool {
pub fn new(initial_size: usize, capacity: usize) -> Self {
let mut free_list = Vec::with_capacity(initial_size);
for _ in 0..initial_size {
free_list.push(MBuf::with_capacity(capacity));
}
Self {
free_list: Mutex::new(free_list),
allocated_count: AtomicUsize::new(0),
capacity,
}
}
pub fn alloc(&self) -> MBuf {
let mut free_list = self.free_list.lock().unwrap();
self.allocated_count.fetch_add(1, Ordering::Relaxed);
if let Some(buf) = free_list.pop() {
return buf;
}
MBuf::with_capacity(self.capacity)
}
pub fn free(&self, buf: MBuf) {
let mut free_list = self.free_list.lock().unwrap();
free_list.push(buf);
self.allocated_count.fetch_sub(1, Ordering::Relaxed);
}
pub fn allocated_count(&self) -> usize {
self.allocated_count.load(Ordering::Relaxed)
}
pub fn free_count(&self) -> usize {
let a =self.free_list.lock().unwrap().len();
println!("free_count: {}", a);
a
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mbuf_pool() {
let pool = MPool::new(2, 1024);
assert_eq!(pool.free_count(), 2);
assert_eq!(pool.allocated_count(), 0);
let buf1 = pool.alloc();
assert_eq!(pool.free_count(), 1);
assert_eq!(pool.allocated_count(), 1);
let buf2 = pool.alloc();
assert_eq!(pool.free_count(), 0);
assert_eq!(pool.allocated_count(), 2);
pool.free(buf1);
assert_eq!(pool.free_count(), 1);
assert_eq!(pool.allocated_count(), 1);
pool.free(buf2);
assert_eq!(pool.free_count(), 2);
assert_eq!(pool.allocated_count(), 0);
}
}