iota_util_mem/
allocators.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5// Copyright 2020 Parity Technologies
6//
7// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
8// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
9// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
10// option. This file may not be copied, modified, or distributed
11// except according to those terms.
12
13#[cfg(not(feature = "std"))]
14use core::ffi::c_void;
15#[cfg(feature = "std")]
16use std::os::raw::c_void;
17
18#[cfg(feature = "std")]
19use crate::malloc_size::MallocUnconditionalSizeOf;
20use crate::malloc_size::{MallocSizeOf, MallocSizeOfOps, VoidPtrToSizeFn};
21
22mod usable_size {
23
24    use super::*;
25
26    cfg_if::cfg_if! {
27
28        if #[cfg(any(
29            target_arch = "wasm32",
30            feature = "estimate-heapsize",
31        ))] {
32
33            // do not try system allocator
34
35            /// Warning this is for compatibility only.
36            /// This function does panic: `estimate-heapsize` feature needs to be activated
37            /// to avoid this function call.
38            pub unsafe extern "C" fn malloc_usable_size(_ptr: *const c_void) -> usize {
39                unreachable!("estimate heapsize only")
40            }
41
42        } else if #[cfg(any(
43            target_os = "linux",
44            target_os = "android",
45            target_os = "freebsd",
46        ))] {
47            // Linux/BSD call system allocator (currently malloc).
48            extern "C" {
49                pub fn malloc_usable_size(ptr: *const c_void) -> usize;
50            }
51
52        } else {
53            // default allocator for non linux or windows system use estimate
54            pub unsafe extern "C" fn malloc_usable_size(_ptr: *const c_void) -> usize {
55                unreachable!("estimate heapsize or feature allocator needed")
56            }
57
58        }
59
60    }
61
62    /// No enclosing function defined.
63    #[inline]
64    pub fn new_enclosing_size_fn() -> Option<VoidPtrToSizeFn> {
65        None
66    }
67}
68
69/// Get a new instance of a MallocSizeOfOps
70pub fn new_malloc_size_ops() -> MallocSizeOfOps {
71    MallocSizeOfOps::new(
72        usable_size::malloc_usable_size,
73        usable_size::new_enclosing_size_fn(),
74        None,
75    )
76}
77
78/// Extension methods for `MallocSizeOf` trait, do not implement
79/// directly.
80/// It allows getting heapsize without exposing `MallocSizeOfOps`
81/// (a single default `MallocSizeOfOps` is used for each call).
82pub trait MallocSizeOfExt: MallocSizeOf {
83    /// Method to launch a heapsize measurement with a
84    /// fresh state.
85    fn malloc_size_of(&self) -> usize {
86        let mut ops = new_malloc_size_ops();
87        <Self as MallocSizeOf>::size_of(self, &mut ops)
88    }
89}
90
91impl<T: MallocSizeOf> MallocSizeOfExt for T {}
92
93#[cfg(feature = "std")]
94impl<T: MallocSizeOf> MallocSizeOf for std::sync::Arc<T> {
95    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
96        self.unconditional_size_of(ops)
97    }
98}