#![macro_use] use as_slice::{AsMutSlice, AsSlice}; use core::cmp; use core::fmt; use core::hash::{Hash, Hasher}; use core::mem::MaybeUninit; use core::ops::{Deref, DerefMut}; use core::sync::atomic::{AtomicU32, Ordering}; use crate::fmt::{assert, *}; struct AtomicBitset where [AtomicU32; (N + 31) / 32]: Sized, { used: [AtomicU32; (N + 31) / 32], } impl AtomicBitset where [AtomicU32; (N + 31) / 32]: Sized, { const fn new() -> Self { const Z: AtomicU32 = AtomicU32::new(0); Self { used: [Z; (N + 31) / 32], } } fn alloc(&self) -> Option { for (i, val) in self.used.iter().enumerate() { let res = val.fetch_update(Ordering::AcqRel, Ordering::Acquire, |val| { let n = val.trailing_ones() as usize + i * 32; if n >= N { None } else { Some(val | (1 << n)) } }); if let Ok(val) = res { let n = val.trailing_ones() as usize + i * 32; return Some(n); } } None } fn free(&self, i: usize) { assert!(i < N); self.used[i / 32].fetch_and(!(1 << ((i % 32) as u32)), Ordering::AcqRel); } } pub trait Pool { fn alloc(&self) -> Option<*mut T>; unsafe fn free(&self, p: *mut T); } pub struct BitPool where [AtomicU32; (N + 31) / 32]: Sized, { used: AtomicBitset, data: MaybeUninit<[T; N]>, } impl BitPool where [AtomicU32; (N + 31) / 32]: Sized, { pub const fn new() -> Self { Self { used: AtomicBitset::new(), data: MaybeUninit::uninit(), } } } impl Pool for BitPool where [AtomicU32; (N + 31) / 32]: Sized, { fn alloc(&self) -> Option<*mut T> { let n = self.used.alloc()?; let origin = self.data.as_ptr() as *mut T; Some(unsafe { origin.add(n) }) } /// safety: p must be a pointer obtained from self.alloc that hasn't been freed yet. unsafe fn free(&self, p: *mut T) { let origin = self.data.as_ptr() as *mut T; let n = p.offset_from(origin); assert!(n >= 0); assert!((n as usize) < N); self.used.free(n as usize); } } pub trait StaticPool: 'static { type Item: 'static; type Pool: Pool; fn get() -> &'static Self::Pool; } pub struct Box { ptr: *mut P::Item, } impl Box

{ pub fn new(item: P::Item) -> Option { let p = match P::get().alloc() { Some(p) => p, None => { warn!("alloc failed!"); return None; } }; //trace!("allocated {:u32}", p as u32); unsafe { p.write(item) }; Some(Self { ptr: p }) } } impl Drop for Box

{ fn drop(&mut self) { unsafe { //trace!("dropping {:u32}", self.ptr as u32); self.ptr.drop_in_place(); P::get().free(self.ptr); }; } } unsafe impl Send for Box

where P::Item: Send {} unsafe impl Sync for Box

where P::Item: Sync {} unsafe impl stable_deref_trait::StableDeref for Box

{} impl AsSlice for Box

where P::Item: AsSlice, { type Element = ::Element; fn as_slice(&self) -> &[Self::Element] { self.deref().as_slice() } } impl AsMutSlice for Box

where P::Item: AsMutSlice, { fn as_mut_slice(&mut self) -> &mut [Self::Element] { self.deref_mut().as_mut_slice() } } impl Deref for Box

{ type Target = P::Item; fn deref(&self) -> &P::Item { unsafe { &*self.ptr } } } impl DerefMut for Box

{ fn deref_mut(&mut self) -> &mut P::Item { unsafe { &mut *self.ptr } } } impl fmt::Debug for Box

where P::Item: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(self, f) } } impl fmt::Display for Box

where P::Item: fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ::fmt(self, f) } } impl PartialEq for Box

where P::Item: PartialEq, { fn eq(&self, rhs: &Box

) -> bool { ::eq(self, rhs) } } impl Eq for Box

where P::Item: Eq {} impl PartialOrd for Box

where P::Item: PartialOrd, { fn partial_cmp(&self, rhs: &Box

) -> Option { ::partial_cmp(self, rhs) } } impl Ord for Box

where P::Item: Ord, { fn cmp(&self, rhs: &Box

) -> cmp::Ordering { ::cmp(self, rhs) } } impl Hash for Box

where P::Item: Hash, { fn hash(&self, state: &mut H) where H: Hasher, { ::hash(self, state) } } macro_rules! pool { ($vis:vis $name:ident: [$ty:ty; $size:expr]) => { $vis struct $name; impl StaticPool for $name { type Item = $ty; type Pool = BitPool<$ty, $size>; fn get() -> &'static Self::Pool { static POOL: BitPool<$ty, $size> = BitPool::new(); &POOL } } }; }