use crate::sync::NullLock; use crate::sync::interface::Mutex; const CHAR_COUNT: usize = 20; const CHAR_POOL_SIZE: usize = CHAR_COUNT + 2; #[derive(Copy,Clone)] pub struct CharCell { pub data: char, next: Option<*mut CharCell>, } impl CharCell { pub const fn new() -> Self { Self { data: '\0', next: None, } } } use core::fmt::{Debug,Formatter,Result}; impl Debug for CharCell { fn fmt(&self, f: &mut Formatter<'_>) -> Result { write!(f, "{}", self.data) } } unsafe impl Send for CharCell {} pub struct CharAllocator(NullLock<[CharCell; CHAR_POOL_SIZE]>); impl CharAllocator { pub const fn new() -> Self { Self(NullLock::new([CharCell::new(); CHAR_POOL_SIZE])) } pub fn init(&self) { self.0.lock(|char_pool| { for idx in 2..CHAR_POOL_SIZE { if idx != CHAR_POOL_SIZE - 1 { char_pool[idx].next = Some(&mut char_pool[idx+1] as *mut CharCell); } else { char_pool[idx].next = None; } } char_pool[0].next = Some(&mut char_pool[2] as *mut CharCell); char_pool[1].next = Some(&mut char_pool[CHAR_POOL_SIZE-1] as *mut CharCell); }); } pub fn alloc(&self) -> Option<&mut CharCell> { return self.0.lock(|char_pool| { if let Some(char_cell) = char_pool[0].next { char_pool[0].next = unsafe{(*char_cell).next}; unsafe { (*char_cell).next = None; } return Some(unsafe{&mut *char_cell as &mut CharCell}); } else { return None; } }); } pub fn free(&self, cell: &mut CharCell) { self.0.lock(|char_pool| { cell.next = None; match char_pool[1].next { None => { char_pool[0].next = Some(cell as *mut CharCell); } Some(ocell) => { unsafe { (*ocell).next = Some(cell as *mut CharCell); } } } char_pool[1].next = Some(cell as *mut CharCell); }); } } impl Debug for CharAllocator { fn fmt(&self, f: &mut Formatter<'_>) -> Result { self.0.lock(|pool| { write!(f, "{:?}", pool) }) } } pub static CHAR_ALLOCATOR: CharAllocator = CharAllocator::new();