use std::{mem::ManuallyDrop, ops::Deref};
use crate::Allocator;
mod standard;
use standard::StandardAllocatorPool;
#[cfg(all(feature = "fixed_size", target_pointer_width = "64", target_endian = "little"))]
mod fixed_size;
#[cfg(all(feature = "fixed_size", target_pointer_width = "64", target_endian = "little"))]
use fixed_size::FixedSizeAllocatorPool;
#[cfg(all(feature = "fixed_size", target_pointer_width = "64", target_endian = "little"))]
pub use fixed_size::{FixedSizeAllocatorMetadata, free_fixed_size_allocator};
#[repr(transparent)]
pub struct AllocatorPool(AllocatorPoolInner);
enum AllocatorPoolInner {
Standard(StandardAllocatorPool),
#[cfg(all(feature = "fixed_size", target_pointer_width = "64", target_endian = "little"))]
FixedSize(FixedSizeAllocatorPool),
}
impl AllocatorPool {
pub fn new(thread_count: usize) -> AllocatorPool {
Self(AllocatorPoolInner::Standard(StandardAllocatorPool::new(thread_count)))
}
#[cfg(feature = "fixed_size")]
pub fn new_fixed_size(thread_count: usize) -> AllocatorPool {
#[cfg(all(target_pointer_width = "64", target_endian = "little"))]
{
Self(AllocatorPoolInner::FixedSize(FixedSizeAllocatorPool::new(thread_count)))
}
#[cfg(not(all(target_pointer_width = "64", target_endian = "little")))]
{
let _thread_count = thread_count; panic!("Fixed size allocators are only supported on 64-bit little-endian platforms");
}
}
pub fn get(&self) -> AllocatorGuard<'_> {
let allocator = match &self.0 {
AllocatorPoolInner::Standard(pool) => pool.get(),
#[cfg(all(
feature = "fixed_size",
target_pointer_width = "64",
target_endian = "little"
))]
AllocatorPoolInner::FixedSize(pool) => pool.get(),
};
AllocatorGuard { allocator: ManuallyDrop::new(allocator), pool: self }
}
fn add(&self, allocator: Allocator) {
unsafe {
match &self.0 {
AllocatorPoolInner::Standard(pool) => pool.add(allocator),
#[cfg(all(
feature = "fixed_size",
target_pointer_width = "64",
target_endian = "little"
))]
AllocatorPoolInner::FixedSize(pool) => pool.add(allocator),
}
}
}
}
pub struct AllocatorGuard<'alloc_pool> {
allocator: ManuallyDrop<Allocator>,
pool: &'alloc_pool AllocatorPool,
}
impl Deref for AllocatorGuard<'_> {
type Target = Allocator;
fn deref(&self) -> &Self::Target {
&self.allocator
}
}
impl Drop for AllocatorGuard<'_> {
fn drop(&mut self) {
let allocator = unsafe { ManuallyDrop::take(&mut self.allocator) };
self.pool.add(allocator);
}
}