#![cfg(feature = "nightly")]
#![cfg_attr(feature = "nightly", feature(allocator_api))]
use std::alloc::Layout;
use std::ptr::NonNull;
#[cfg(feature = "nightly")]
use std::alloc::{AllocError, Allocator};
use std::sync::Arc;
use crate::core::global::GlobalState;
use crate::core::tls;
#[derive(Clone)]
pub struct FrameAllocator {
_marker: std::marker::PhantomData<*const ()>,
}
impl FrameAllocator {
pub fn new() -> Self {
Self {
_marker: std::marker::PhantomData,
}
}
}
impl Default for FrameAllocator {
fn default() -> Self {
Self::new()
}
}
unsafe impl Allocator for FrameAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let ptr = tls::with_tls(|tls| {
tls.frame_alloc_layout(layout)
});
NonNull::new(ptr)
.map(|p| NonNull::slice_from_raw_parts(p, layout.size()))
.ok_or(AllocError)
}
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
}
}
#[derive(Clone)]
pub struct PoolAllocator {
global: Arc<GlobalState>,
}
impl PoolAllocator {
pub fn new(global: Arc<GlobalState>) -> Self {
Self { global }
}
}
unsafe impl Allocator for PoolAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let ptr = tls::with_tls(|tls| {
tls.pool_alloc_layout(layout, &self.global)
});
NonNull::new(ptr)
.map(|p| NonNull::slice_from_raw_parts(p, layout.size()))
.ok_or(AllocError)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
tls::with_tls(|tls| {
tls.pool_free_layout(ptr.as_ptr(), layout, &self.global);
});
}
}
#[derive(Clone)]
pub struct HeapAllocator {
global: Arc<GlobalState>,
}
impl HeapAllocator {
pub fn new(global: Arc<GlobalState>) -> Self {
Self { global }
}
}
unsafe impl Allocator for HeapAllocator {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
let ptr = self.global.heap_alloc_layout(layout);
NonNull::new(ptr)
.map(|p| NonNull::slice_from_raw_parts(p, layout.size()))
.ok_or(AllocError)
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
self.global.heap_free_layout(ptr.as_ptr(), layout);
}
}