use std::cell::RefCell;
use std::sync::LazyLock;
pub mod allocator;
pub mod api;
pub mod arena;
pub mod central_pool;
pub mod config;
pub mod error;
pub mod free_list;
pub mod global_alloc;
pub mod header;
pub mod large_object;
pub mod size_class;
pub mod stats;
pub mod thread_cache;
use crate::thread_cache::ThreadCacheHandle;
use crate::{allocator::Allocator as AllocatorType, error::InitError as InitErrorType};
static GLOBAL_ALLOCATOR: LazyLock<Result<AllocatorType, InitErrorType>> =
LazyLock::new(|| AllocatorType::new(AllocatorConfig::default()));
thread_local! {
static THREAD_CACHE: RefCell<Option<ThreadCacheHandle>> = const { RefCell::new(None) };
}
fn global_allocator() -> Result<&'static Allocator, &'static InitError> {
GLOBAL_ALLOCATOR.as_ref()
}
pub(crate) fn try_with_thread_cache<R>(
f: impl FnOnce(&Allocator, &mut ThreadCache) -> R,
) -> Result<Option<R>, &'static InitError> {
let allocator = global_allocator()?;
THREAD_CACHE
.try_with(|cache| {
let Ok(mut handle) = cache.try_borrow_mut() else {
return Ok(None);
};
let handle = handle.get_or_insert_with(|| ThreadCacheHandle::new(allocator));
Ok(Some(handle.with_parts(f)))
})
.unwrap_or(Ok(None))
}
pub use crate::allocator::Allocator;
pub use crate::api::{allocate, deallocate, deallocate_with_size, global_stats};
pub use crate::config::AllocatorConfig;
pub use crate::error::{AllocError, FreeError, InitError};
pub use crate::global_alloc::OrthotopeGlobalAlloc;
pub use crate::size_class::SizeClass;
pub use crate::stats::{AllocatorStats, SizeClassStats, ThreadCacheStats};
pub use crate::thread_cache::ThreadCache;