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()
39        .apply();
40});
41
42#[cfg(not(feature = "fast_allocator"))]
43use std::alloc::System;
44
45
46#[cfg(not(feature = "fast_allocator"))]
47static mut SAND: System = System;
48
49#[cfg(feature = "fast_allocator_options")]
50#[inline(always)]
51pub fn set_and_init_allocator_options(options_init_fn: Option<fn()>)
52{
53    if let Some(fx) = options_init_fn {
54        unsafe {
55            GLOBAL_ALLOC_OPTS = LazyLock::new(fx);
56        }
57    }
58
59    unsafe { *GLOBAL_ALLOC_OPTS }
60}
61
62#[inline(always)]
63pub unsafe fn direct_alloc(layout: Layout) -> *mut u8 {
64    #[cfg(feature = "fast_allocator_options")]
65    set_and_init_allocator_options(None);
66    SAND.alloc(layout)
67}
68
69#[inline(always)]
70pub unsafe fn direct_dealloc(ptr: *mut u8, layout: Layout) {
71    SAND.dealloc(ptr, layout)
72}
73
74pub struct DirectAllocator;
75
76unsafe impl Allocator for DirectAllocator {
77    #[inline(always)]
78    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
79        let ptr = unsafe { direct_alloc(layout) };
80        let slice = unsafe { std::slice::from_raw_parts_mut(ptr, layout.size()) };
81        Ok(cast_to_nonnull::<[u8]>(slice))
82    }
83    #[inline(always)]
84    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
85        direct_dealloc(ptr.as_ptr(), layout);
86    }
87}
88
89pub static DIRECT_ALLOCATOR: DirectAllocator = DirectAllocator;
90