From a93a4ca1867efd857aeb3a82e3c192b020097fdf Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Fri, 2 Apr 2021 16:14:00 +0200 Subject: [PATCH] with error --- src/main.rs | 97 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 18 deletions(-) diff --git a/src/main.rs b/src/main.rs index fb3a7bd..bf3864e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,11 @@ impl<T> RacyCell<T> { //unsafe impl<T> Sync for RacyCell<T> where T: Sync {} unsafe impl<T> Sync for RacyCell<T> {} +#[derive(Debug)] +enum Error { + Unitialized, + OutOfMemory, +} struct Box<T: 'static + Sized, const S: usize> { // data: &'static mut T, index: usize, @@ -30,21 +35,30 @@ struct Box<T: 'static + Sized, const S: usize> { impl<T: 'static, const S: usize> Drop for Box<T, S> { fn drop(&mut self) { - self.allocator.dealloc(self.index) + unsafe { self.allocator.dealloc(self.index) } } } impl<T: 'static, const S: usize> Deref for Box<T, S> { type Target = T; fn deref(&self) -> &T { - unsafe { &self.allocator.data.get_mut_unchecked()[self.index] } + unsafe { + self.allocator + .data /* RacyCell */ + .get_mut_unchecked() /* Array */ + .get_unchecked(self.index) + } } } impl<T: 'static, const S: usize> DerefMut for Box<T, S> { - // type Target = T; fn deref_mut(&mut self) -> &mut T { - unsafe { &mut self.allocator.data.get_mut_unchecked()[self.index] } + unsafe { + self.allocator + .data /* RacyCell */ + .get_mut_unchecked() /* Array */ + .get_unchecked_mut(self.index) + } } } @@ -72,6 +86,9 @@ where } fn init(&self) { + if *unsafe { self.init.get_mut_unchecked() } { + panic!("already initialized") + }; let free = unsafe { self.free.get_mut_unchecked() }; for (index, value) in free.iter_mut().enumerate() { *value = index + 1; @@ -81,30 +98,31 @@ where println!("init : free {:?}", unsafe { self.free.get_mut_unchecked() }); } - fn dealloc(&self, index: usize) { - unsafe { - if !*self.init.get_mut_unchecked() { - panic!(); - } - self.free.get_mut_unchecked()[index] = *self.head.get_mut_unchecked(); - *self.head.get_mut_unchecked() = index; - } + // dealloc can only be called by dropping Box + // which can happen only if already initialized + // in a library we could hide this as a crate local + unsafe fn dealloc(&self, index: usize) { + self.free.get_mut_unchecked()[index] = *self.head.get_mut_unchecked(); + *self.head.get_mut_unchecked() = index; + println!("dealloc index {}", index) } - fn alloc(&'static self) -> Result<Box<T, S>, ()> { + fn alloc(&'static self) -> Result<Box<T, S>, Error> { unsafe { if !*self.init.get_mut_unchecked() { - panic!(); + return Err(Error::Unitialized); } let index = *self.head.get_mut_unchecked(); println!("index {}", self.head.get_mut_unchecked()); println!("head {}", self.head.get_mut_unchecked()); - *self.head.get_mut_unchecked() = self.free.get_mut_unchecked()[index]; - println!("new head {}", self.head.get_mut_unchecked()); - if *self.head.get_mut_unchecked() > S { - Err(()) + if *self.head.get_mut_unchecked() >= S { + Err(Error::OutOfMemory) } else { + *self.head.get_mut_unchecked() = + *self.free.get_mut_unchecked().get_unchecked_mut(index); + println!("new head {}", self.head.get_mut_unchecked()); + Ok(Box { index, allocator: self, @@ -114,6 +132,49 @@ where } } +mod tests { + use super::*; + static P: PoolMan<u32, 2> = PoolMan::new([0; 2]); + + #[test] + fn test() { + P.init(); + { + let e = P.alloc().unwrap(); + println!("e {}", *e); + mem::drop(e); + let mut e1 = P.alloc().unwrap(); + println!("e1 {}", *e1); + *e1 = 2; + println!("e1 {}", *e1); + + let e2 = P.alloc().unwrap(); + println!("e2 {}", *e2); + } + let e = P.alloc().unwrap(); + println!("e {}", *e); + } + + #[test] + fn test2() { + P.init(); + { + let e = P.alloc().unwrap(); + println!("e {}", *e); + mem::drop(e); + let mut e1 = P.alloc().unwrap(); + println!("e1 {}", *e1); + *e1 = 2; + println!("e1 {}", *e1); + + let e2 = P.alloc().unwrap(); + println!("e2 {}", *e2); + } + let e = P.alloc().unwrap(); + println!("e {}", *e); + } +} + static P: PoolMan<u32, 2> = PoolMan::new([0; 2]); fn main() { P.init(); -- GitLab