mimalloc_rust/
lib.rs

1#![cfg_attr(feature = "unstable", feature(allocator_api))]
2#![cfg_attr(not(test), no_std)]
3
4//! this crate provides the best binding for [mimalloc](https://github.com/microsoft/mimalloc)
5//! # Example Usage
6//! first add to dependencies
7//! ```toml
8//! [dependencies]
9//! mimalloc-rust = "0.2"
10//! ```
11//! then set the global allocator
12//! ```rust
13//! use mimalloc_rust::*;
14//!
15//! #[global_allocator]
16//! static GLOBAL_MIMALLOC: GlobalMiMalloc = GlobalMiMalloc;
17//! ```
18//! # Allocator API!
19//! ```
20//! #![feature(allocator_api)]
21//! use std::{ffi::c_void, mem::ManuallyDrop};
22//!
23//! use mimalloc_rust::{
24//!     heap::{HeapVisitor, MiMallocHeap},
25//!     raw::{
26//!         heap::{mi_heap_area_t, mi_heap_delete, mi_heap_new},
27//!         types::mi_heap_t,
28//!     },
29//!     with_heap, GlobalMiMalloc,
30//! };
31//!
32//! #[derive(Debug, Clone)]
33//! struct TestHeap {
34//!     heap: *mut mi_heap_t,
35//! }
36//! use std::ops::Deref;
37//! impl Deref for TestHeap {
38//!     type Target = *mut mi_heap_t;
39//!
40//!     fn deref(&self) -> &Self::Target {
41//!         &self.heap
42//!     }
43//! }
44//!
45//! impl TestHeap {
46//!     fn new() -> Self {
47//!         Self {
48//!             heap: unsafe { mi_heap_new() },
49//!         }
50//!     }
51//! }
52//!
53//! impl Drop for TestHeap {
54//!     fn drop(&mut self) {
55//!         unsafe { mi_heap_delete(self.heap) }
56//!     }
57//! }
58//!
59//! #[test]
60//! fn test_allocator_api() {
61//!     let allocator = MiMallocHeap::new(TestHeap::new());
62//!     let mut b: Vec<u8, &MiMallocHeap<TestHeap>> = Vec::new_in(&allocator);
63//!     b.push(1);
64//!     b.push(2);
65//!     assert_eq!(b[0], 1);
66//!     assert_eq!(b[1], 2);
67//! }
68//!
69//! ```
70
71#[cfg(test)]
72mod tests;
73
74pub mod heap;
75use cty::c_long;
76use heap::*;
77// the hand writed native binding
78pub use mimalloc_rust_sys as raw;
79use raw::types::mi_heap_t;
80
81use core::{
82    alloc::{GlobalAlloc, Layout},
83    ffi::c_void,
84    fmt::Debug,
85    ops::Deref,
86};
87
88use crate::raw::{aligned_allocation::*, basic_allocation::*, heap::*, runtime_options::*};
89/// The global allocator
90pub struct GlobalMiMalloc;
91
92impl Debug for GlobalMiMalloc {
93    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
94        let ptr = GlobalMiMalloc::get().heap.heap;
95        let r = unsafe { &mut *ptr };
96        f.write_fmt(format_args!("Global MiMalloc {:?}: {:?}", ptr, r))
97    }
98}
99impl GlobalMiMalloc {
100    /// replace the global allocator by a heap
101    #[inline]
102    pub fn replace_by<T: Deref<Target = *mut mi_heap_t>>(
103        heap: &MiMallocHeap<T>,
104    ) -> MiMallocHeapGlobal {
105        MiMallocHeap {
106            heap: GlobalHeap {
107                heap: unsafe { mi_heap_set_default(*heap.heap.deref()) },
108            },
109        }
110    }
111
112    /// get the default heap type of the global allocator holds
113    #[inline]
114    pub fn get() -> MiMallocHeapGlobal {
115        MiMallocHeap {
116            heap: GlobalHeap {
117                heap: unsafe { mi_heap_get_default() },
118            },
119        }
120    }
121
122    #[inline]
123    pub fn option_disable(option: mi_option_t) {
124        unsafe { mi_option_disable(option) }
125    }
126
127    #[inline]
128    pub fn option_enable(option: mi_option_t) {
129        unsafe { mi_option_enable(option) }
130    }
131
132    #[inline]
133    pub fn option_get(option: mi_option_t) -> c_long {
134        unsafe { mi_option_get(option) }
135    }
136
137    #[inline]
138    pub fn option_is_enabled(option: mi_option_t) -> bool {
139        unsafe { mi_option_is_enabled(option) }
140    }
141
142    #[inline]
143    pub fn option_set(option: mi_option_t, value: c_long) {
144        unsafe { mi_option_set(option, value) }
145    }
146
147    #[inline]
148    pub fn option_set_default(option: mi_option_t, value: c_long) {
149        unsafe { mi_option_set_default(option, value) }
150    }
151
152    #[inline]
153    pub fn option_set_enabled(option: mi_option_t) {
154        unsafe { mi_option_set_enabled(option) }
155    }
156
157    #[inline]
158    pub fn option_set_enabled_default(option: mi_option_t) {
159        unsafe { mi_option_set_enabled_default(option) }
160    }
161}
162unsafe impl GlobalAlloc for GlobalMiMalloc {
163    #[inline]
164    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
165        mi_malloc_aligned(layout.size(), layout.align()) as *mut u8
166    }
167
168    #[inline]
169    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
170        mi_free(ptr as *mut c_void);
171    }
172
173    #[inline]
174    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
175        mi_zalloc_aligned(layout.size(), layout.align()) as *mut u8
176    }
177
178    #[inline]
179    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
180        mi_realloc_aligned(ptr as *mut c_void, new_size, layout.align()) as *mut u8
181    }
182}