Skip to content
Snippets Groups Projects
Commit 904f6891 authored by Per Lindgren's avatar Per Lindgren
Browse files

works but not static

parent 83868d29
No related branches found
No related tags found
No related merge requests found
use core::mem;
use poolman::PoolMan;
use poolman::{PoolMan, P};
#[derive(Debug)]
struct IDrop(u32);
......
......@@ -42,37 +42,27 @@ pub enum Error {
AlreadyInitialized,
}
pub struct Box<T: 'static + Sized, const S: usize> {
pub struct Box<T: 'static + Sized> {
index: usize,
allocator: &'static PoolMan<T, S>,
p: &'static dyn P<T>,
}
impl<T: 'static, const S: usize> Drop for Box<T, S> {
impl<T: 'static> Drop for Box<T> {
fn drop(&mut self) {
self.allocator.dealloc(self.index)
self.p.dealloc(self.index)
}
}
impl<T: 'static, const S: usize> Deref for Box<T, S> {
impl<T: 'static> Deref for Box<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
self.allocator
.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked(self.index)
}
self.p.deref_index(self.index)
}
}
impl<T: 'static, const S: usize> DerefMut for Box<T, S> {
impl<T: 'static> DerefMut for Box<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
self.allocator
.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked_mut(self.index)
}
self.p.deref_mut_index(self.index)
}
}
......@@ -83,6 +73,50 @@ pub struct PoolMan<T: 'static, const S: usize> {
init: RacyCell<bool>,
}
pub trait P<T> {
fn deref_index(&self, index: usize) -> &T;
fn deref_mut_index(&self, index: usize) -> &mut T;
fn dealloc(&self, index: usize);
}
impl<T: 'static, const S: usize> P<T> for PoolMan<T, S> {
#[inline]
fn deref_index(&self, index: usize) -> &T {
unsafe {
self.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked(index)
}
}
#[inline]
fn deref_mut_index(&self, index: usize) -> &mut T {
unsafe {
self.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked_mut(index)
}
}
// Safety:
// dealloc can only be called by dropping Box
// which can happen only if already initialized
// thus it is safe to assume init == true
//
// not accissible from user code
#[inline]
fn dealloc(&self, index: usize) {
interrupt_free(|| unsafe {
*self.free.get_mut_unchecked().get_unchecked_mut(index) =
*self.head.get_mut_unchecked();
*self.head.get_mut_unchecked() = index;
});
}
}
unsafe impl<T: 'static, const S: usize> Sync for PoolMan<T, S> {}
unsafe impl<T: 'static, const S: usize> Send for PoolMan<T, S> {}
impl<T, const S: usize> PoolMan<T, S>
where
T: Sized,
......@@ -115,38 +149,26 @@ where
})
}
// Safety:
// dealloc can only be called by dropping Box
// which can happen only if already initialized
// thus it is safe to assume init == true
//
// not accissible from user code
#[inline]
fn dealloc(&self, index: usize) {
interrupt_free(|| unsafe {
*self.free.get_mut_unchecked().get_unchecked_mut(index) =
*self.head.get_mut_unchecked();
*self.head.get_mut_unchecked() = index;
});
}
#[inline]
pub fn alloc(&'static self) -> Result<Box<T, S>, Error> {
pub fn alloc(&'static self) -> Result<Box<T>, Error> {
// this check does not need to be inside of critical section
// as initialization is monotonic, cannot be undone
if !unsafe { *self.init.get_mut_unchecked() } {
Err(Error::Uninitialized)
} else {
interrupt_free(|| unsafe {
let index = *self.head.get_mut_unchecked();
*self.head.get_mut_unchecked() =
*self.free.get_mut_unchecked().get_unchecked(index);
if *self.head.get_mut_unchecked() > S {
// head of free list
let head = *self.head.get_mut_unchecked();
if head >= S {
Err(Error::OutOfMemory)
} else {
// update head to `next` free
*self.head.get_mut_unchecked() =
*self.free.get_mut_unchecked().get_unchecked(head);
Ok(Box {
index,
allocator: self,
index: head,
// allocator: self,
p: self,
})
}
})
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment