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

pool trait

parent 83868d29
No related branches found
No related tags found
No related merge requests found
......@@ -3,6 +3,7 @@ use poolman::PoolMan;
#[derive(Debug)]
struct IDrop(u32);
unsafe impl Sync for IDrop(u32) {}
impl core::ops::Drop for IDrop {
fn drop(&mut self) {
......@@ -15,17 +16,17 @@ static P: PoolMan<IDrop, 2> = PoolMan::new([IDrop(10), IDrop(11)]);
fn main() {
P.init();
{
let e = P.alloc().unwrap();
let e = P.allocb().unwrap();
println!("e {:?}", *e);
mem::drop(e);
let mut e1 = P.alloc().unwrap();
let mut e1 = P.allocb().unwrap();
println!("e1 {:?}", *e1);
*e1 = IDrop(2);
println!("e1 {:?}", *e1);
let e2 = P.alloc().unwrap();
let e2 = P.allocb().unwrap();
println!("e2 {:?}", *e2);
}
let e = P.alloc().unwrap();
let e = P.allocb().unwrap();
println!("e {:?}", *e);
}
#![no_std]
use core::cell::UnsafeCell;
// use core::marker::PhantomData;
use core::ops::{Deref, DerefMut, Drop};
use cortex_m::interrupt;
......@@ -42,40 +43,73 @@ pub enum Error {
AlreadyInitialized,
}
pub struct Box<T: 'static + Sized, const S: usize> {
trait Pool<T>
where
T: Send + Sync,
{
fn dealloc(&'static self, index: usize);
fn index_deref(&'static self, index: usize) -> &T;
fn index_deref_mut(&'static self, index: usize) -> &mut T;
}
pub struct B<T: 'static + Sized + Send + Sync> {
index: usize,
allocator: &'static PoolMan<T, S>,
allocator: &'static dyn Pool<T>,
}
impl<T: 'static, const S: usize> Drop for Box<T, S> {
impl<T: 'static + Sized + Send + Sync> Drop for B<T> {
fn drop(&mut self) {
self.allocator.dealloc(self.index)
}
}
impl<T: 'static, const S: usize> Deref for Box<T, S> {
impl<T: 'static + Sized + Send + Sync> Deref for B<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
self.allocator
.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked(self.index)
}
self.allocator.index_deref(self.index)
}
}
impl<T: 'static, const S: usize> DerefMut for Box<T, S> {
impl<T: 'static + Sized + Send + Sync> DerefMut for B<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
self.allocator
.data /* RacyCell */
.get_mut_unchecked() /* Array */
.get_unchecked_mut(self.index)
}
self.allocator.index_deref_mut(self.index)
}
}
// pub struct Box<T: 'static + Sized, const S: usize> {
// index: usize,
// allocator: &'static PoolMan<T, S>,
// }
// impl<T: 'static, const S: usize> Drop for Box<T, S> {
// fn drop(&mut self) {
// 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 /* RacyCell */
// .get_mut_unchecked() /* Array */
// .get_unchecked(self.index)
// }
// }
// }
// impl<T: 'static, const S: usize> DerefMut for Box<T, S> {
// fn deref_mut(&mut self) -> &mut T {
// unsafe {
// self.allocator
// .data /* RacyCell */
// .get_mut_unchecked() /* Array */
// .get_unchecked_mut(self.index)
// }
// }
// }
pub struct PoolMan<T: 'static, const S: usize> {
data: RacyCell<[T; S]>,
free: RacyCell<[usize; S]>,
......@@ -83,13 +117,15 @@ pub struct PoolMan<T: 'static, const S: usize> {
init: RacyCell<bool>,
}
impl<T, const S: usize> PoolMan<T, S>
where
T: Sized,
T: Sized + Send + Sync,
{
pub const fn new(v: [T; S]) -> Self
where
T: Sized,
T: Sized + Send + Sync,
{
Self {
data: RacyCell::new(v),
......@@ -115,23 +151,45 @@ 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;
});
}
// // 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 accessible 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> {
// #[inline]
// pub fn alloc(&'static self) -> Result<Box<T, S>, 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 {
// Err(Error::OutOfMemory)
// } else {
// Ok(Box {
// index,
// allocator: self,
// })
// }
// })
// }
// }
pub fn allocb(&'static self) -> Result<B<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() } {
......@@ -144,7 +202,7 @@ where
if *self.head.get_mut_unchecked() > S {
Err(Error::OutOfMemory)
} else {
Ok(Box {
Ok(B {
index,
allocator: self,
})
......@@ -153,3 +211,26 @@ where
}
}
}
// sealed, should only be externally accessible
impl<T, const S: usize> Pool<T> for PoolMan<T, S>
where
T: Sized + Send + Sync,
{
#[inline]
fn dealloc(&'static 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;
});
}
fn index_deref(&'static self, index: usize) -> &'static T {
unsafe { self.data.get_mut_unchecked().get_unchecked(index) }
}
fn index_deref_mut(&'static self, index: usize) -> &'static mut T {
unsafe { self.data.get_mut_unchecked().get_unchecked_mut(index) }
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment