Skip to main content

rumtk_arena/mem/
alloc.rs

1/*
2 *     rumtk attempts to implement HL7 and medical protocols for interoperability in medicine.
3 *     This toolkit aims to be reliable, simple, performant, and standards compliant.
4 *     Copyright (C) 2026  Luis M. Santos, M.D. <lsantos@medicalmasses.com>
5 *     Copyright (C) 2026  MedicalMasses L.L.C. <contact@medicalmasses.com>
6 *
7 *     This program is free software: you can redistribute it and/or modify
8 *     it under the terms of the GNU General Public License as published by
9 *     the Free Software Foundation, either version 3 of the License, or
10 *     (at your option) any later version.
11 *
12 *     This program is distributed in the hope that it will be useful,
13 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *     GNU General Public License for more details.
16 *
17 *     You should have received a copy of the GNU General Public License
18 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
19 */
20use std::alloc::{AllocError, Allocator};
21use std::alloc::{GlobalAlloc, Layout};
22use std::sync::LazyLock;
23
24use crate::mem::cast_to_nonnull;
25use std::ptr::NonNull;
26
27#[cfg(feature = "fast_allocator")]
28use mimalloc::MiMalloc;
29
30#[cfg(feature = "fast_allocator")]
31static mut SAND: MiMalloc = MiMalloc;
32
33#[cfg(feature = "fast_allocator_options")]
34use crate::mem::alloc_opts::MiMallocOpts;
35
36#[cfg(feature = "fast_allocator_options")]
37static mut GLOBAL_ALLOC_OPTS: LazyLock<()> = LazyLock::new(|| {
38    MiMallocOpts::builder().apply();
39});
40
41#[cfg(not(feature = "fast_allocator"))]
42use std::alloc::System;
43
44#[cfg(not(feature = "fast_allocator"))]
45static mut SAND: System = System;
46
47#[cfg(feature = "fast_allocator_options")]
48#[inline(always)]
49pub fn set_and_init_allocator_options(options_init_fn: Option<fn()>)
50{
51    if let Some(fx) = options_init_fn {
52        unsafe {
53            GLOBAL_ALLOC_OPTS = LazyLock::new(fx);
54        }
55    }
56
57    unsafe { *GLOBAL_ALLOC_OPTS }
58}
59
60#[inline(always)]
61pub unsafe fn direct_alloc(layout: Layout) -> *mut u8 {
62    #[cfg(feature = "fast_allocator_options")]
63    set_and_init_allocator_options(None);
64    SAND.alloc(layout)
65}
66
67#[inline(always)]
68pub unsafe fn direct_dealloc(ptr: *mut u8, layout: Layout) {
69    SAND.dealloc(ptr, layout)
70}
71
72pub struct DirectAllocator;
73
74unsafe impl Allocator for DirectAllocator {
75    #[inline(always)]
76    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
77        let ptr = unsafe { direct_alloc(layout) };
78        let slice = unsafe { std::slice::from_raw_parts_mut(ptr, layout.size()) };
79        Ok(cast_to_nonnull::<[u8]>(slice))
80    }
81    #[inline(always)]
82    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
83        direct_dealloc(ptr.as_ptr(), layout);
84    }
85}
86
87pub static DIRECT_ALLOCATOR: DirectAllocator = DirectAllocator;
88