use memory::bucket::Bucket;
use memory::bucket::BUCKET_PAGES;
use memory::page::Page;
use memory::pool::Pool;
use std::ptr::null_mut;
use std::usize::MAX;
pub struct Heap {
map: usize,
pools: [*mut Pool; BUCKET_PAGES],
}
impl Heap {
pub fn create() -> Heap {
Heap {
map: MAX,
pools: [null_mut(); BUCKET_PAGES],
}
}
pub fn allocate_page(&mut self) -> *mut Page {
if self.map == 0 {
panic!("Not more than one heap supported currently.");
}
let index = Bucket::find_least_position(self.map) - 1;
if self.pools[index] == null_mut() {
self.pools[index] = Pool::create(self);
}
unsafe { (*self.pools[index]).allocate_page() }
}
pub fn get_allocation_position(&self, pool: *mut Pool) -> usize {
for i in 0..BUCKET_PAGES {
if pool == self.pools[i] {
return i;
}
}
panic!(
"The pool pointer {:X} is not from my pools array!",
pool as usize
)
}
pub fn get_allocation_bit(&self, pool: *mut Pool) -> usize {
1 << (BUCKET_PAGES - 1 - self.get_allocation_position(pool))
}
pub fn mark_as_full(&mut self, pool: *mut Pool) {
let bit = self.get_allocation_bit(pool);
self.map = self.map & !bit;
}
pub fn mark_as_free(&mut self, pool: *mut Pool) {
let bit = self.get_allocation_bit(pool);
self.map = self.map | bit;
}
pub fn deallocate(&mut self, pool: *mut Pool) {
let position = self.get_allocation_position(pool);
self.pools[position] = null_mut();
unsafe {
(*pool).deallocate();
}
}
pub fn empty(&self) {
if self.map != MAX {
panic! {"Heap map: {:X}", self.map};
}
for i in 0..BUCKET_PAGES {
if self.pools[i] != null_mut() {
unsafe {
(*self.pools[i]).deallocate();
}
}
}
}
}