#[cfg(feature = "std")]
use crate::malloc_size::MallocUnconditionalSizeOf;
use crate::malloc_size::{MallocSizeOf, MallocSizeOfOps, VoidPtrToSizeFn};
#[cfg(not(feature = "std"))]
use core::ffi::c_void;
#[cfg(feature = "std")]
use std::os::raw::c_void;
mod usable_size {
use super::*;
cfg_if::cfg_if! {
if #[cfg(any(
target_arch = "wasm32",
feature = "estimate-heapsize",
feature = "dlmalloc-global",
))] {
pub unsafe extern "C" fn malloc_usable_size(_ptr: *const c_void) -> usize {
unreachable!("estimate heapsize only")
}
} else if #[cfg(target_os = "windows")] {
use winapi::um::heapapi::{GetProcessHeap, HeapSize, HeapValidate};
use winapi::ctypes::c_void as winapi_c_void;
pub unsafe extern "C" fn malloc_usable_size(mut ptr: *const c_void) -> usize {
let heap = GetProcessHeap();
if HeapValidate(heap, 0, ptr as *const winapi_c_void) == 0 {
ptr = *(ptr as *const *const c_void).offset(-1);
}
HeapSize(heap, 0, ptr as *const winapi_c_void) as usize
}
} else if #[cfg(feature = "jemalloc-global")] {
pub unsafe extern "C" fn malloc_usable_size(ptr: *const c_void) -> usize {
tikv_jemallocator::usable_size(ptr)
}
} else if #[cfg(feature = "mimalloc-global")] {
pub unsafe extern "C" fn malloc_usable_size(ptr: *const c_void) -> usize {
libmimalloc_sys::mi_usable_size(ptr as *mut _)
}
} else if #[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "freebsd",
))] {
extern "C" {
pub fn malloc_usable_size(ptr: *const c_void) -> usize;
}
} else {
pub unsafe extern "C" fn malloc_usable_size(_ptr: *const c_void) -> usize {
unreachable!("estimate heapsize or feature allocator needed")
}
}
}
#[inline]
pub fn new_enclosing_size_fn() -> Option<VoidPtrToSizeFn> {
None
}
}
pub fn new_malloc_size_ops() -> MallocSizeOfOps {
MallocSizeOfOps::new(usable_size::malloc_usable_size, usable_size::new_enclosing_size_fn(), None)
}
pub trait MallocSizeOfExt: MallocSizeOf {
fn malloc_size_of(&self) -> usize {
let mut ops = new_malloc_size_ops();
<Self as MallocSizeOf>::size_of(self, &mut ops)
}
}
impl<T: MallocSizeOf> MallocSizeOfExt for T {}
#[cfg(feature = "std")]
impl<T: MallocSizeOf> MallocSizeOf for std::sync::Arc<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.unconditional_size_of(ops)
}
}