Skip to content

Instantly share code, notes, and snippets.

@smj-edison
Last active November 9, 2023 00:04
Show Gist options
  • Save smj-edison/0410d5942f5999a11cd4a84c2687ef95 to your computer and use it in GitHub Desktop.
Save smj-edison/0410d5942f5999a11cd4a84c2687ef95 to your computer and use it in GitHub Desktop.
Fix filename
use std::{
alloc::Layout,
cell::UnsafeCell,
fmt::Debug,
mem::size_of,
ptr::{self, NonNull},
};
use allocator_api2::alloc::AllocError;
use buddy_system_allocator::Heap;
pub struct Alloc<'a, T> {
pub value: &'a mut T,
buddy_ref: &'a BuddyArena,
ptr: NonNull<u8>,
layout: Layout,
}
impl<'a, T: Debug> Debug for Alloc<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Allocation {{ ")?;
self.value.fmt(f)?;
write!(f, " }}")
}
}
impl<'a, T> Drop for Alloc<'a, T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(self.value as *mut T);
}
unsafe { &mut *self.buddy_ref.heap.get() }.dealloc(self.ptr, self.layout);
}
}
pub struct BuddyArena {
_space: Vec<usize>,
heap: UnsafeCell<Heap<32>>,
}
impl BuddyArena {
pub fn new(bytes: usize) -> BuddyArena {
let size = bytes / size_of::<usize>();
let mut heap = Heap::<32>::new();
let space = vec![0; size];
unsafe {
heap.init(
space.as_slice().as_ptr() as usize,
size * size_of::<usize>(),
);
}
BuddyArena {
_space: space,
heap: heap.into(),
}
}
pub fn alloc_with<'a, T, F>(&'a self, f: F) -> Result<Alloc<'a, T>, AllocError>
where
F: FnOnce() -> T,
{
let layout = Layout::new::<T>();
let alloc = unsafe { self.heap_ref() }
.alloc(layout)
.map_err(|_| AllocError)?;
let p = alloc.as_ptr() as *mut T;
let ref_to_x = unsafe {
ptr::write(p, f());
&mut *p
};
Ok(Alloc {
value: ref_to_x,
buddy_ref: &self,
ptr: alloc,
layout,
})
}
unsafe fn heap_ref(&self) -> &mut Heap<32> {
&mut *self.heap.get()
}
}
#[test]
fn test_alloc() {
let arena = BuddyArena::new(1_000_000);
let hello = arena.alloc_with(|| "hello").unwrap();
let world = arena.alloc_with(|| "world").unwrap();
let arr = arena.alloc_with(|| [hello, world]).unwrap();
println!("{:?}", arr);
println!("{:?}", unsafe { arena.heap_ref() });
println!("{:?}", unsafe { arena.heap_ref() });
drop(arr);
println!("done");
println!("{:?}", unsafe { arena.heap_ref() });
}
[package]
name = "api-test"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
allocator-api2 = "0.2.15"
buddy_system_allocator = "0.9.0"
self_cell = "1.0.1"
pub mod buddy_arena;
use std::cell::UnsafeCell;
use buddy_arena::Alloc;
use buddy_arena::BuddyArena;
use self_cell::self_cell;
#[derive(Debug, Clone)]
pub enum Osc {
NoteOn { channel: u8, note: u8, velocity: u8 },
NoteOff { channel: u8, note: u8, velocity: u8 },
}
struct TraverserIo<'arena> {
osc_io: Vec<UnsafeCell<Alloc<'arena, Osc>>>,
}
self_cell!(
struct TraverserIoWithArena {
owner: BuddyArena,
#[covariant]
dependent: TraverserIo,
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment