use std::ptr;
pub trait MemElemUtils {
fn free_ptr_get(&self) -> *mut Self;
fn free_ptr_set(&mut self, ptr: *mut Self);
}
pub trait MemElem:
MemElemUtils +
Default +
{}
impl<TElem> MemElem for TElem where TElem:
MemElemUtils +
Default +
{}
struct MemChunk<TElem: MemElem> {
data: Vec<TElem>,
}
pub struct MemPool<TElem: MemElem> {
chunks: Vec<MemChunk<TElem>>,
chunk_size: usize,
free: *mut TElem,
}
impl <TElem: MemElem> MemPool<TElem> {
pub fn new(
chunk_size: usize,
) -> MemPool<TElem> {
MemPool {
chunks: vec![
MemChunk {
data: Vec::with_capacity(chunk_size),
},
],
chunk_size: chunk_size,
free: ptr::null_mut(),
}
}
pub fn clear(
&mut self,
) {
self.chunks.truncate(1);
self.chunks[0].data.clear();
debug_assert!(self.chunks[0].data.capacity() == self.chunk_size);
self.free = ptr::null_mut();
}
#[allow(dead_code)]
pub fn alloc_elem(
&mut self,
) -> *mut TElem {
if self.free.is_null() {
if self.chunks.last().unwrap().data.len() == self.chunk_size {
self.chunks.push(MemChunk {
data: Vec::with_capacity(self.chunk_size),
});
}
let chunk = self.chunks.last_mut().unwrap();
chunk.data.push(TElem::default());
return chunk.data.last_mut().unwrap();
} else {
let elem = self.free;
self.free = unsafe { (*elem).free_ptr_get() };
return unsafe { &mut *elem };
}
}
pub fn alloc_elem_from(
&mut self,
from: TElem,
) -> *mut TElem {
if self.free.is_null() {
if self.chunks.last().unwrap().data.len() == self.chunk_size {
self.chunks.push(MemChunk {
data: Vec::with_capacity(self.chunk_size),
});
}
let chunk = self.chunks.last_mut().unwrap();
chunk.data.push(from);
return chunk.data.last_mut().unwrap();
} else {
let elem = self.free;
unsafe {
self.free = (*elem).free_ptr_get();
ptr::write(elem, from);
}
return unsafe { &mut *elem };
}
}
pub fn free_elem(
&mut self,
elem: *mut TElem,
) {
unsafe {
(*elem).free_ptr_set(self.free);
}
self.free = elem;
}
}