2019-06-19 16:26:12 -07:00
/* ----------------------------------------------------------------------------
2023-03-06 09:02:38 -08:00
Copyright ( c ) 2018 - 2023 , Microsoft Research , Daan Leijen
2019-06-19 16:26:12 -07:00
This is free software ; you can redistribute it and / or modify it under the
terms of the MIT license . A copy of the license can be found in the file
2019-06-23 19:53:34 +08:00
" LICENSE " at the root of this distribution .
2019-06-19 16:26:12 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
# pragma once
2019-06-26 12:57:13 +08:00
# ifndef MIMALLOC_H
# define MIMALLOC_H
2019-06-19 16:26:12 -07:00
2024-05-16 19:07:14 -07:00
# define MI_MALLOC_VERSION 217 // major + 2 digits minor
2019-06-19 16:26:12 -07:00
// ------------------------------------------------------
// Compiler specific attributes
// ------------------------------------------------------
# ifdef __cplusplus
2020-01-16 15:58:48 -08:00
# if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
2019-06-19 16:26:12 -07:00
# define mi_attr_noexcept noexcept
2020-01-16 15:58:48 -08:00
# else
# define mi_attr_noexcept throw()
2019-06-19 16:26:12 -07:00
# endif
# else
# define mi_attr_noexcept
# endif
2020-09-04 10:40:05 -07:00
# if defined(__cplusplus) && (__cplusplus >= 201703)
2020-02-01 17:48:26 -08:00
# define mi_decl_nodiscard [[nodiscard]]
2021-06-24 17:29:06 +08:00
# elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) // includes clang, icc, and clang-cl
2020-02-01 17:48:26 -08:00
# define mi_decl_nodiscard __attribute__((warn_unused_result))
2022-12-03 00:23:43 +01:00
# elif defined(_HAS_NODISCARD)
2022-11-28 09:15:16 -08:00
# define mi_decl_nodiscard _NODISCARD
2020-04-20 17:59:13 -07:00
# elif (_MSC_VER >= 1700)
2022-12-03 00:23:43 +01:00
# define mi_decl_nodiscard _Check_return_
2020-04-20 17:59:13 -07:00
# else
# define mi_decl_nodiscard
# endif
2020-02-01 17:29:30 -08:00
2020-04-06 09:53:29 -07:00
# if defined(_MSC_VER) || defined(__MINGW32__)
2019-06-19 16:26:12 -07:00
# if !defined(MI_SHARED_LIB)
# define mi_decl_export
# elif defined(MI_SHARED_LIB_EXPORT)
2020-02-01 17:48:26 -08:00
# define mi_decl_export __declspec(dllexport)
2019-06-19 16:26:12 -07:00
# else
2020-02-01 17:48:26 -08:00
# define mi_decl_export __declspec(dllimport)
2019-06-19 16:26:12 -07:00
# endif
2020-04-06 10:56:53 -07:00
# if defined(__MINGW32__)
# define mi_decl_restrict
# define mi_attr_malloc __attribute__((malloc))
2019-06-19 16:26:12 -07:00
# else
2020-04-06 10:56:53 -07:00
# if (_MSC_VER >= 1900) && !defined(__EDG__)
# define mi_decl_restrict __declspec(allocator) __declspec(restrict)
# else
# define mi_decl_restrict __declspec(restrict)
# endif
# define mi_attr_malloc
2019-06-19 16:26:12 -07:00
# endif
2020-02-01 17:48:26 -08:00
# define mi_cdecl __cdecl
2019-06-19 16:26:12 -07:00
# define mi_attr_alloc_size(s)
# define mi_attr_alloc_size2(s1,s2)
2020-01-19 22:14:35 -08:00
# define mi_attr_alloc_align(p)
2020-02-01 17:48:26 -08:00
# elif defined(__GNUC__) // includes clang and icc
2021-10-27 17:01:12 -07:00
# if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT)
# define mi_decl_export __attribute__((visibility("default")))
# else
# define mi_decl_export
# endif
2020-02-01 17:48:26 -08:00
# define mi_cdecl // leads to warnings... __attribute__((cdecl))
2020-02-13 10:36:39 -08:00
# define mi_decl_restrict
2020-02-01 17:48:26 -08:00
# define mi_attr_malloc __attribute__((malloc))
2020-01-19 22:14:35 -08:00
# if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5)
2020-02-01 17:48:26 -08:00
# define mi_attr_alloc_size(s)
# define mi_attr_alloc_size2(s1,s2)
# define mi_attr_alloc_align(p)
2020-01-19 22:14:35 -08:00
# elif defined(__INTEL_COMPILER)
2020-02-01 17:48:26 -08:00
# define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
# define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
# define mi_attr_alloc_align(p)
2019-06-19 16:26:12 -07:00
# else
2020-02-01 17:48:26 -08:00
# define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
# define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
# define mi_attr_alloc_align(p) __attribute__((alloc_align(p)))
2019-06-19 16:26:12 -07:00
# endif
# else
2020-01-19 22:14:35 -08:00
# define mi_cdecl
2019-06-19 16:26:12 -07:00
# define mi_decl_export
2020-02-13 10:36:39 -08:00
# define mi_decl_restrict
2019-06-19 16:26:12 -07:00
# define mi_attr_malloc
# define mi_attr_alloc_size(s)
# define mi_attr_alloc_size2(s1,s2)
2020-01-19 22:14:35 -08:00
# define mi_attr_alloc_align(p)
2019-06-19 16:26:12 -07:00
# endif
// ------------------------------------------------------
// Includes
// ------------------------------------------------------
2019-08-29 09:42:50 -07:00
# include <stddef.h> // size_t
2019-06-19 16:26:12 -07:00
# include <stdbool.h> // bool
2022-10-30 19:47:54 -07:00
# include <stdint.h> // INTPTR_MAX
2019-06-19 16:26:12 -07:00
# ifdef __cplusplus
extern " C " {
# endif
// ------------------------------------------------------
// Standard malloc interface
// ------------------------------------------------------
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_malloc ( size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_calloc ( size_t count , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 1 , 2 ) ;
mi_decl_nodiscard mi_decl_export void * mi_realloc ( void * p , size_t newsize ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) ;
mi_decl_export void * mi_expand ( void * p , size_t newsize ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) ;
2019-06-19 16:26:12 -07:00
2020-02-01 17:48:26 -08:00
mi_decl_export void mi_free ( void * p ) mi_attr_noexcept ;
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict char * mi_strdup ( const char * s ) mi_attr_noexcept mi_attr_malloc ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict char * mi_strndup ( const char * s , size_t n ) mi_attr_noexcept mi_attr_malloc ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict char * mi_realpath ( const char * fname , char * resolved_name ) mi_attr_noexcept mi_attr_malloc ;
2019-06-19 16:26:12 -07:00
// ------------------------------------------------------
// Extended functionality
// ------------------------------------------------------
# define MI_SMALL_WSIZE_MAX (128)
# define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*))
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_malloc_small ( size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_zalloc_small ( size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_zalloc ( size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
2019-06-19 16:26:12 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_mallocn ( size_t count , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 1 , 2 ) ;
mi_decl_nodiscard mi_decl_export void * mi_reallocn ( void * p , size_t count , size_t size ) mi_attr_noexcept mi_attr_alloc_size2 ( 2 , 3 ) ;
mi_decl_nodiscard mi_decl_export void * mi_reallocf ( void * p , size_t newsize ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) ;
2019-06-19 16:26:12 -07:00
2020-02-01 17:29:30 -08:00
mi_decl_nodiscard mi_decl_export size_t mi_usable_size ( const void * p ) mi_attr_noexcept ;
mi_decl_nodiscard mi_decl_export size_t mi_good_size ( size_t size ) mi_attr_noexcept ;
2019-06-19 16:26:12 -07:00
2019-08-29 09:42:50 -07:00
2020-01-17 19:59:55 -08:00
// ------------------------------------------------------
// Internals
// ------------------------------------------------------
2020-01-16 14:25:09 -08:00
typedef void ( mi_cdecl mi_deferred_free_fun ) ( bool force , unsigned long long heartbeat , void * arg ) ;
2020-01-15 10:21:32 -08:00
mi_decl_export void mi_register_deferred_free ( mi_deferred_free_fun * deferred_free , void * arg ) mi_attr_noexcept ;
2019-08-29 09:42:50 -07:00
2020-01-16 14:25:09 -08:00
typedef void ( mi_cdecl mi_output_fun ) ( const char * msg , void * arg ) ;
2020-01-15 10:18:32 -08:00
mi_decl_export void mi_register_output ( mi_output_fun * out , void * arg ) mi_attr_noexcept ;
2019-08-29 09:42:50 -07:00
2020-01-17 19:59:55 -08:00
typedef void ( mi_cdecl mi_error_fun ) ( int err , void * arg ) ;
mi_decl_export void mi_register_error ( mi_error_fun * fun , void * arg ) ;
2019-08-29 09:42:50 -07:00
2019-06-19 16:26:12 -07:00
mi_decl_export void mi_collect ( bool force ) mi_attr_noexcept ;
2019-08-29 09:42:50 -07:00
mi_decl_export int mi_version ( void ) mi_attr_noexcept ;
2019-06-24 17:03:33 +02:00
mi_decl_export void mi_stats_reset ( void ) mi_attr_noexcept ;
2019-08-29 09:01:00 -07:00
mi_decl_export void mi_stats_merge ( void ) mi_attr_noexcept ;
2020-01-15 10:53:54 -08:00
mi_decl_export void mi_stats_print ( void * out ) mi_attr_noexcept ; // backward compatibility: `out` is ignored and should be NULL
mi_decl_export void mi_stats_print_out ( mi_output_fun * out , void * arg ) mi_attr_noexcept ;
2019-06-19 16:26:12 -07:00
2019-06-24 17:03:33 +02:00
mi_decl_export void mi_process_init ( void ) mi_attr_noexcept ;
mi_decl_export void mi_thread_init ( void ) mi_attr_noexcept ;
mi_decl_export void mi_thread_done ( void ) mi_attr_noexcept ;
2020-01-15 10:53:54 -08:00
mi_decl_export void mi_thread_stats_print_out ( mi_output_fun * out , void * arg ) mi_attr_noexcept ;
2019-06-19 16:26:12 -07:00
2022-12-03 00:23:43 +01:00
mi_decl_export void mi_process_info ( size_t * elapsed_msecs , size_t * user_msecs , size_t * system_msecs ,
size_t * current_rss , size_t * peak_rss ,
2020-09-24 10:13:25 -07:00
size_t * current_commit , size_t * peak_commit , size_t * page_faults ) mi_attr_noexcept ;
2019-06-19 16:26:12 -07:00
2019-09-03 10:57:39 -07:00
// -------------------------------------------------------------------------------------
2019-06-19 16:26:12 -07:00
// Aligned allocation
2019-09-03 10:57:39 -07:00
// Note that `alignment` always follows `size` for consistency with unaligned
// allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
// -------------------------------------------------------------------------------------
2022-11-06 16:23:42 -08:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_malloc_aligned ( size_t size , size_t alignment ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) mi_attr_alloc_align ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_malloc_aligned_at ( size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_zalloc_aligned ( size_t size , size_t alignment ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) mi_attr_alloc_align ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_zalloc_aligned_at ( size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_calloc_aligned ( size_t count , size_t size , size_t alignment ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 1 , 2 ) mi_attr_alloc_align ( 3 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_calloc_aligned_at ( size_t count , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 1 , 2 ) ;
mi_decl_nodiscard mi_decl_export void * mi_realloc_aligned ( void * p , size_t newsize , size_t alignment ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) mi_attr_alloc_align ( 3 ) ;
mi_decl_nodiscard mi_decl_export void * mi_realloc_aligned_at ( void * p , size_t newsize , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) ;
2019-06-19 16:26:12 -07:00
2020-01-17 19:59:55 -08:00
// -------------------------------------------------------------------------------------
// Heaps: first-class, but can only allocate from the same thread that created it.
// -------------------------------------------------------------------------------------
2020-02-01 17:48:26 -08:00
2019-06-19 16:26:12 -07:00
struct mi_heap_s ;
typedef struct mi_heap_s mi_heap_t ;
2020-02-01 17:29:30 -08:00
mi_decl_nodiscard mi_decl_export mi_heap_t * mi_heap_new ( void ) ;
2019-06-19 16:26:12 -07:00
mi_decl_export void mi_heap_delete ( mi_heap_t * heap ) ;
mi_decl_export void mi_heap_destroy ( mi_heap_t * heap ) ;
mi_decl_export mi_heap_t * mi_heap_set_default ( mi_heap_t * heap ) ;
2019-06-24 17:03:33 +02:00
mi_decl_export mi_heap_t * mi_heap_get_default ( void ) ;
mi_decl_export mi_heap_t * mi_heap_get_backing ( void ) ;
2019-06-19 16:26:12 -07:00
mi_decl_export void mi_heap_collect ( mi_heap_t * heap , bool force ) mi_attr_noexcept ;
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_malloc ( mi_heap_t * heap , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_zalloc ( mi_heap_t * heap , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_calloc ( mi_heap_t * heap , size_t count , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 2 , 3 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_mallocn ( mi_heap_t * heap , size_t count , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 2 , 3 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_malloc_small ( mi_heap_t * heap , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) ;
2019-06-19 16:26:12 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export void * mi_heap_realloc ( mi_heap_t * heap , void * p , size_t newsize ) mi_attr_noexcept mi_attr_alloc_size ( 3 ) ;
2020-08-29 19:30:38 -07:00
mi_decl_nodiscard mi_decl_export void * mi_heap_reallocn ( mi_heap_t * heap , void * p , size_t count , size_t size ) mi_attr_noexcept mi_attr_alloc_size2 ( 3 , 4 ) ;
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export void * mi_heap_reallocf ( mi_heap_t * heap , void * p , size_t newsize ) mi_attr_noexcept mi_attr_alloc_size ( 3 ) ;
2019-07-08 17:17:07 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict char * mi_heap_strdup ( mi_heap_t * heap , const char * s ) mi_attr_noexcept mi_attr_malloc ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict char * mi_heap_strndup ( mi_heap_t * heap , const char * s , size_t n ) mi_attr_noexcept mi_attr_malloc ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict char * mi_heap_realpath ( mi_heap_t * heap , const char * fname , char * resolved_name ) mi_attr_noexcept mi_attr_malloc ;
2019-06-19 16:26:12 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_malloc_aligned ( mi_heap_t * heap , size_t size , size_t alignment ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) mi_attr_alloc_align ( 3 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_malloc_aligned_at ( mi_heap_t * heap , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_zalloc_aligned ( mi_heap_t * heap , size_t size , size_t alignment ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) mi_attr_alloc_align ( 3 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_zalloc_aligned_at ( mi_heap_t * heap , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_calloc_aligned ( mi_heap_t * heap , size_t count , size_t size , size_t alignment ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 2 , 3 ) mi_attr_alloc_align ( 4 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_calloc_aligned_at ( mi_heap_t * heap , size_t count , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2 ( 2 , 3 ) ;
mi_decl_nodiscard mi_decl_export void * mi_heap_realloc_aligned ( mi_heap_t * heap , void * p , size_t newsize , size_t alignment ) mi_attr_noexcept mi_attr_alloc_size ( 3 ) mi_attr_alloc_align ( 4 ) ;
mi_decl_nodiscard mi_decl_export void * mi_heap_realloc_aligned_at ( mi_heap_t * heap , void * p , size_t newsize , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_alloc_size ( 3 ) ;
2019-07-08 17:17:07 -07:00
2019-06-19 16:26:12 -07:00
2019-09-03 10:57:39 -07:00
// --------------------------------------------------------------------------------
2019-09-11 20:49:18 -07:00
// Zero initialized re-allocation.
// Only valid on memory that was originally allocated with zero initialization too.
2019-09-03 10:57:39 -07:00
// e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
// see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
// --------------------------------------------------------------------------------
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export void * mi_rezalloc ( void * p , size_t newsize ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export void * mi_recalloc ( void * p , size_t newcount , size_t size ) mi_attr_noexcept mi_attr_alloc_size2 ( 2 , 3 ) ;
2019-09-03 10:57:39 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export void * mi_rezalloc_aligned ( void * p , size_t newsize , size_t alignment ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) mi_attr_alloc_align ( 3 ) ;
mi_decl_nodiscard mi_decl_export void * mi_rezalloc_aligned_at ( void * p , size_t newsize , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export void * mi_recalloc_aligned ( void * p , size_t newcount , size_t size , size_t alignment ) mi_attr_noexcept mi_attr_alloc_size2 ( 2 , 3 ) mi_attr_alloc_align ( 4 ) ;
mi_decl_nodiscard mi_decl_export void * mi_recalloc_aligned_at ( void * p , size_t newcount , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_alloc_size2 ( 2 , 3 ) ;
2019-09-03 10:57:39 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export void * mi_heap_rezalloc ( mi_heap_t * heap , void * p , size_t newsize ) mi_attr_noexcept mi_attr_alloc_size ( 3 ) ;
mi_decl_nodiscard mi_decl_export void * mi_heap_recalloc ( mi_heap_t * heap , void * p , size_t newcount , size_t size ) mi_attr_noexcept mi_attr_alloc_size2 ( 3 , 4 ) ;
2019-09-03 10:57:39 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export void * mi_heap_rezalloc_aligned ( mi_heap_t * heap , void * p , size_t newsize , size_t alignment ) mi_attr_noexcept mi_attr_alloc_size ( 3 ) mi_attr_alloc_align ( 4 ) ;
mi_decl_nodiscard mi_decl_export void * mi_heap_rezalloc_aligned_at ( mi_heap_t * heap , void * p , size_t newsize , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_alloc_size ( 3 ) ;
mi_decl_nodiscard mi_decl_export void * mi_heap_recalloc_aligned ( mi_heap_t * heap , void * p , size_t newcount , size_t size , size_t alignment ) mi_attr_noexcept mi_attr_alloc_size2 ( 3 , 4 ) mi_attr_alloc_align ( 5 ) ;
mi_decl_nodiscard mi_decl_export void * mi_heap_recalloc_aligned_at ( mi_heap_t * heap , void * p , size_t newcount , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept mi_attr_alloc_size2 ( 3 , 4 ) ;
2019-09-03 10:57:39 -07:00
2019-06-19 16:26:12 -07:00
// ------------------------------------------------------
// Analysis
// ------------------------------------------------------
mi_decl_export bool mi_heap_contains_block ( mi_heap_t * heap , const void * p ) ;
mi_decl_export bool mi_heap_check_owned ( mi_heap_t * heap , const void * p ) ;
mi_decl_export bool mi_check_owned ( const void * p ) ;
// An area of heap space contains blocks of a single size.
typedef struct mi_heap_area_s {
void * blocks ; // start of the area containing heap blocks
size_t reserved ; // bytes reserved for this area (virtual)
size_t committed ; // current available bytes for this area
2021-12-19 14:51:15 +01:00
size_t used ; // number of allocated blocks
2019-06-19 16:26:12 -07:00
size_t block_size ; // size in bytes of each block
2022-04-08 16:58:32 -07:00
size_t full_block_size ; // size in bytes of a full block including padding and metadata.
2019-06-19 16:26:12 -07:00
} mi_heap_area_t ;
2019-07-07 21:59:53 -07:00
typedef bool ( mi_cdecl mi_block_visit_fun ) ( const mi_heap_t * heap , const mi_heap_area_t * area , void * block , size_t block_size , void * arg ) ;
2019-06-19 16:26:12 -07:00
mi_decl_export bool mi_heap_visit_blocks ( const mi_heap_t * heap , bool visit_all_blocks , mi_block_visit_fun * visitor , void * arg ) ;
2019-09-04 12:00:41 -07:00
// Experimental
2020-02-01 17:29:30 -08:00
mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region ( const void * p ) mi_attr_noexcept ;
2020-08-29 19:30:38 -07:00
mi_decl_nodiscard mi_decl_export bool mi_is_redirected ( void ) mi_attr_noexcept ;
2019-07-18 18:59:32 -07:00
2019-11-13 13:35:50 -08:00
mi_decl_export int mi_reserve_huge_os_pages_interleave ( size_t pages , size_t numa_nodes , size_t timeout_msecs ) mi_attr_noexcept ;
2019-11-06 22:49:01 -08:00
mi_decl_export int mi_reserve_huge_os_pages_at ( size_t pages , int numa_node , size_t timeout_msecs ) mi_attr_noexcept ;
2019-11-01 19:53:07 -07:00
2020-09-07 21:34:34 -07:00
mi_decl_export int mi_reserve_os_memory ( size_t size , bool commit , bool allow_large ) mi_attr_noexcept ;
mi_decl_export bool mi_manage_os_memory ( void * start , size_t size , bool is_committed , bool is_large , bool is_zero , int numa_node ) mi_attr_noexcept ;
2024-03-01 16:24:28 -08:00
mi_decl_export void mi_debug_show_arenas ( bool show_inuse , bool show_abandoned , bool show_purge ) mi_attr_noexcept ;
2020-09-07 21:34:34 -07:00
2022-11-01 14:00:20 -07:00
// Experimental: heaps associated with specific memory arena's
typedef int mi_arena_id_t ;
2022-11-01 16:26:17 -07:00
mi_decl_export void * mi_arena_area ( mi_arena_id_t arena_id , size_t * size ) ;
mi_decl_export int mi_reserve_huge_os_pages_at_ex ( size_t pages , int numa_node , size_t timeout_msecs , bool exclusive , mi_arena_id_t * arena_id ) mi_attr_noexcept ;
mi_decl_export int mi_reserve_os_memory_ex ( size_t size , bool commit , bool allow_large , bool exclusive , mi_arena_id_t * arena_id ) mi_attr_noexcept ;
mi_decl_export bool mi_manage_os_memory_ex ( void * start , size_t size , bool is_committed , bool is_large , bool is_zero , int numa_node , bool exclusive , mi_arena_id_t * arena_id ) mi_attr_noexcept ;
2022-11-01 14:00:20 -07:00
2023-04-04 15:40:06 -07:00
# if MI_MALLOC_VERSION >= 182
2022-12-19 18:01:58 -08:00
// Create a heap that only allocates in the specified arena
2022-11-01 16:22:51 -07:00
mi_decl_nodiscard mi_decl_export mi_heap_t * mi_heap_new_in_arena ( mi_arena_id_t arena_id ) ;
2022-11-01 14:00:20 -07:00
# endif
2019-11-01 19:53:07 -07:00
// deprecated
mi_decl_export int mi_reserve_huge_os_pages ( size_t pages , double max_secs , size_t * pages_reserved ) mi_attr_noexcept ;
2020-02-01 17:48:26 -08:00
2019-06-19 16:26:12 -07:00
// ------------------------------------------------------
// Convenience
// ------------------------------------------------------
2020-02-01 17:48:26 -08:00
# define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp)))
# define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp)))
# define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp)))
# define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp)))
# define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp)))
# define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp)))
2019-06-19 16:26:12 -07:00
# define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
# define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
# define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
# define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
2019-09-11 20:49:18 -07:00
# define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp)))
# define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp)))
2019-06-19 16:26:12 -07:00
// ------------------------------------------------------
2022-02-02 19:19:03 -08:00
// Options
2019-06-19 16:26:12 -07:00
// ------------------------------------------------------
typedef enum mi_option_e {
2019-07-15 14:32:54 -07:00
// stable options
2024-04-22 10:10:20 -07:00
mi_option_show_errors , // print error messages
mi_option_show_stats , // print statistics on termination
mi_option_verbose , // print verbose messages
// advanced options
mi_option_eager_commit , // eager commit segments? (after `eager_commit_delay` segments) (=1)
mi_option_arena_eager_commit , // eager commit arenas? Use 2 to enable just on overcommit systems (=2)
mi_option_purge_decommits , // should a memory purge decommit? (=1). Set to 0 to use memory reset on a purge (instead of decommit)
mi_option_allow_large_os_pages , // allow large (2 or 4 MiB) OS pages, implies eager commit. If false, also disables THP for the process.
mi_option_reserve_huge_os_pages , // reserve N huge OS pages (1GiB pages) at startup
mi_option_reserve_huge_os_pages_at , // reserve huge OS pages at a specific NUMA node
2024-05-18 09:56:02 -07:00
mi_option_reserve_os_memory , // reserve specified amount of OS memory in an arena at startup (internally, this value is in KiB; use `mi_option_get_size`)
2022-04-09 15:07:07 -07:00
mi_option_deprecated_segment_cache ,
2023-04-08 17:37:58 -07:00
mi_option_deprecated_page_reset ,
2024-04-22 10:10:20 -07:00
mi_option_abandoned_page_purge , // immediately purge delayed purges on thread termination
2023-04-23 13:04:50 -07:00
mi_option_deprecated_segment_reset ,
2024-04-22 10:10:20 -07:00
mi_option_eager_commit_delay , // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
mi_option_purge_delay , // memory purging is delayed by N milli seconds; use 0 for immediate purging or -1 for no purging at all. (=10)
mi_option_use_numa_nodes , // 0 = use all available numa nodes, otherwise use at most N nodes.
mi_option_disallow_os_alloc , // 1 = do not use OS memory for allocation (but only programmatically reserved arenas)
mi_option_os_tag , // tag used for OS logging (macOS only for now) (=100)
mi_option_max_errors , // issue at most N error messages
mi_option_max_warnings , // issue at most N warning messages
mi_option_max_segment_reclaim , // max. percentage of the abandoned segments can be reclaimed per try (=10%)
mi_option_destroy_on_exit , // if set, release all memory on exit; sometimes used for dynamic unloading but can be unsafe
2024-05-18 09:56:02 -07:00
mi_option_arena_reserve , // initial memory size for arena reservation (= 1 GiB on 64-bit) (internally, this value is in KiB; use `mi_option_get_size`)
2024-04-22 10:10:20 -07:00
mi_option_arena_purge_mult , // multiplier for `purge_delay` for the purging delay for arenas (=10)
2023-04-04 16:44:07 -07:00
mi_option_purge_extend_delay ,
2024-04-22 10:10:20 -07:00
mi_option_abandoned_reclaim_on_free , // allow to reclaim an abandoned segment on a free (=1)
mi_option_disallow_arena_alloc , // 1 = do not use arena's for allocation (except if using specific arena id's)
2024-05-18 09:56:02 -07:00
mi_option_retry_on_oom , // retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. (only on windows)
2023-04-04 12:15:57 -07:00
_mi_option_last ,
2023-04-23 13:04:50 -07:00
// legacy option names
2023-04-05 10:11:54 -07:00
mi_option_large_os_pages = mi_option_allow_large_os_pages ,
2023-04-04 12:15:57 -07:00
mi_option_eager_region_commit = mi_option_arena_eager_commit ,
mi_option_reset_decommits = mi_option_purge_decommits ,
2023-04-05 11:22:36 -07:00
mi_option_reset_delay = mi_option_purge_delay ,
2024-04-22 10:10:20 -07:00
mi_option_abandoned_page_reset = mi_option_abandoned_page_purge ,
mi_option_limit_os_alloc = mi_option_disallow_os_alloc
2019-06-19 16:26:12 -07:00
} mi_option_t ;
2019-07-09 20:24:00 -07:00
2020-02-01 17:48:26 -08:00
mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled ( mi_option_t option ) ;
mi_decl_export void mi_option_enable ( mi_option_t option ) ;
mi_decl_export void mi_option_disable ( mi_option_t option ) ;
mi_decl_export void mi_option_set_enabled ( mi_option_t option , bool enable ) ;
mi_decl_export void mi_option_set_enabled_default ( mi_option_t option , bool enable ) ;
2019-06-19 16:26:12 -07:00
2023-03-30 16:20:11 -07:00
mi_decl_nodiscard mi_decl_export long mi_option_get ( mi_option_t option ) ;
mi_decl_nodiscard mi_decl_export long mi_option_get_clamp ( mi_option_t option , long min , long max ) ;
mi_decl_nodiscard mi_decl_export size_t mi_option_get_size ( mi_option_t option ) ;
2020-02-01 17:48:26 -08:00
mi_decl_export void mi_option_set ( mi_option_t option , long value ) ;
mi_decl_export void mi_option_set_default ( mi_option_t option , long value ) ;
2019-06-19 16:26:12 -07:00
2019-07-07 13:44:33 -07:00
2019-07-18 21:20:18 -07:00
// -------------------------------------------------------------------------------------------------------
// "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions.
// (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.)
2020-02-13 10:36:39 -08:00
// note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing.
2019-07-18 21:20:18 -07:00
// -------------------------------------------------------------------------------------------------------
2019-07-07 13:44:33 -07:00
2020-02-01 17:41:04 -08:00
mi_decl_export void mi_cfree ( void * p ) mi_attr_noexcept ;
mi_decl_export void * mi__expand ( void * p , size_t newsize ) mi_attr_noexcept ;
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export size_t mi_malloc_size ( const void * p ) mi_attr_noexcept ;
2021-11-02 21:52:00 -07:00
mi_decl_nodiscard mi_decl_export size_t mi_malloc_good_size ( size_t size ) mi_attr_noexcept ;
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size ( const void * p ) mi_attr_noexcept ;
2019-07-07 13:44:33 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_export int mi_posix_memalign ( void * * p , size_t alignment , size_t size ) mi_attr_noexcept ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_memalign ( size_t alignment , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) mi_attr_alloc_align ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_valloc ( size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_pvalloc ( size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_aligned_alloc ( size_t alignment , size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 2 ) mi_attr_alloc_align ( 1 ) ;
2019-07-07 13:44:33 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export void * mi_reallocarray ( void * p , size_t count , size_t size ) mi_attr_noexcept mi_attr_alloc_size2 ( 2 , 3 ) ;
2021-12-15 18:54:57 -08:00
mi_decl_nodiscard mi_decl_export int mi_reallocarr ( void * p , size_t count , size_t size ) mi_attr_noexcept ;
2020-02-01 17:29:30 -08:00
mi_decl_nodiscard mi_decl_export void * mi_aligned_recalloc ( void * p , size_t newcount , size_t size , size_t alignment ) mi_attr_noexcept ;
mi_decl_nodiscard mi_decl_export void * mi_aligned_offset_recalloc ( void * p , size_t newcount , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept ;
2019-07-18 18:59:32 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short * mi_wcsdup ( const unsigned short * s ) mi_attr_noexcept mi_attr_malloc ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char * mi_mbsdup ( const unsigned char * s ) mi_attr_noexcept mi_attr_malloc ;
mi_decl_export int mi_dupenv_s ( char * * buf , size_t * size , const char * name ) mi_attr_noexcept ;
2020-02-01 17:41:04 -08:00
mi_decl_export int mi_wdupenv_s ( unsigned short * * buf , size_t * size , const unsigned short * name ) mi_attr_noexcept ;
2019-07-18 21:12:40 -07:00
2020-02-13 10:36:39 -08:00
mi_decl_export void mi_free_size ( void * p , size_t size ) mi_attr_noexcept ;
2019-07-07 18:11:21 -07:00
mi_decl_export void mi_free_size_aligned ( void * p , size_t size , size_t alignment ) mi_attr_noexcept ;
2020-02-13 10:36:39 -08:00
mi_decl_export void mi_free_aligned ( void * p , size_t alignment ) mi_attr_noexcept ;
2019-07-14 19:56:33 -07:00
2020-01-20 15:41:56 -08:00
// The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`.
// (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception).
2020-02-13 10:36:39 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_new ( size_t size ) mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_new_aligned ( size_t size , size_t alignment ) mi_attr_malloc mi_attr_alloc_size ( 1 ) mi_attr_alloc_align ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_new_nothrow ( size_t size ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_new_aligned_nothrow ( size_t size , size_t alignment ) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size ( 1 ) mi_attr_alloc_align ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_new_n ( size_t count , size_t size ) mi_attr_malloc mi_attr_alloc_size2 ( 1 , 2 ) ;
mi_decl_nodiscard mi_decl_export void * mi_new_realloc ( void * p , size_t newsize ) mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export void * mi_new_reallocn ( void * p , size_t newcount , size_t size ) mi_attr_alloc_size2 ( 2 , 3 ) ;
2019-07-14 19:56:33 -07:00
2022-11-22 14:48:26 -08:00
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_alloc_new ( mi_heap_t * heap , size_t size ) mi_attr_malloc mi_attr_alloc_size ( 2 ) ;
mi_decl_nodiscard mi_decl_export mi_decl_restrict void * mi_heap_alloc_new_n ( mi_heap_t * heap , size_t count , size_t size ) mi_attr_malloc mi_attr_alloc_size2 ( 2 , 3 ) ;
2019-07-14 19:56:33 -07:00
2019-06-19 16:26:12 -07:00
# ifdef __cplusplus
}
# endif
2020-01-16 15:57:11 -08:00
// ---------------------------------------------------------------------------------------------
// Implement the C++ std::allocator interface for use in STL containers.
// (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally)
// ---------------------------------------------------------------------------------------------
2020-01-16 15:17:15 -08:00
# ifdef __cplusplus
2021-11-14 15:32:43 -08:00
# include <cstddef> // std::size_t
2020-02-01 17:29:30 -08:00
# include <cstdint> // PTRDIFF_MAX
2020-01-16 15:57:11 -08:00
# if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
2020-01-20 15:27:05 -08:00
# include <type_traits> // std::true_type
# include <utility> // std::forward
2020-01-16 15:57:11 -08:00
# endif
2020-01-16 15:17:15 -08:00
2022-11-24 15:13:19 +01:00
template < class T > struct _mi_stl_allocator_common {
2020-01-22 18:33:07 -08:00
typedef T value_type ;
2020-01-20 15:27:05 -08:00
typedef std : : size_t size_type ;
2020-01-22 18:33:07 -08:00
typedef std : : ptrdiff_t difference_type ;
2020-01-20 15:27:05 -08:00
typedef value_type & reference ;
typedef value_type const & const_reference ;
typedef value_type * pointer ;
typedef value_type const * const_pointer ;
2022-12-03 00:23:43 +01:00
2022-11-24 15:13:19 +01:00
# if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
using propagate_on_container_copy_assignment = std : : true_type ;
using propagate_on_container_move_assignment = std : : true_type ;
using propagate_on_container_swap = std : : true_type ;
template < class U , class . . . Args > void construct ( U * p , Args & & . . . args ) { : : new ( p ) U ( std : : forward < Args > ( args ) . . . ) ; }
template < class U > void destroy ( U * p ) mi_attr_noexcept { p - > ~ U ( ) ; }
# else
void construct ( pointer p , value_type const & val ) { : : new ( p ) value_type ( val ) ; }
void destroy ( pointer p ) { p - > ~ value_type ( ) ; }
# endif
size_type max_size ( ) const mi_attr_noexcept { return ( PTRDIFF_MAX / sizeof ( value_type ) ) ; }
pointer address ( reference x ) const { return & x ; }
const_pointer address ( const_reference x ) const { return & x ; }
} ;
template < class T > struct mi_stl_allocator : public _mi_stl_allocator_common < T > {
using typename _mi_stl_allocator_common < T > : : size_type ;
2022-11-27 13:00:15 -08:00
using typename _mi_stl_allocator_common < T > : : value_type ;
using typename _mi_stl_allocator_common < T > : : pointer ;
2020-01-20 15:27:05 -08:00
template < class U > struct rebind { typedef mi_stl_allocator < U > other ; } ;
2020-02-01 17:41:04 -08:00
mi_stl_allocator ( ) mi_attr_noexcept = default ;
mi_stl_allocator ( const mi_stl_allocator & ) mi_attr_noexcept = default ;
2020-01-20 15:27:05 -08:00
template < class U > mi_stl_allocator ( const mi_stl_allocator < U > & ) mi_attr_noexcept { }
mi_stl_allocator select_on_container_copy_construction ( ) const { return * this ; }
void deallocate ( T * p , size_type ) { mi_free ( p ) ; }
2020-01-22 18:33:07 -08:00
# if (__cplusplus >= 201703L) // C++17
2020-02-01 17:29:30 -08:00
mi_decl_nodiscard T * allocate ( size_type count ) { return static_cast < T * > ( mi_new_n ( count , sizeof ( T ) ) ) ; }
mi_decl_nodiscard T * allocate ( size_type count , const void * ) { return allocate ( count ) ; }
2020-01-22 18:33:07 -08:00
# else
2020-02-01 17:29:30 -08:00
mi_decl_nodiscard pointer allocate ( size_type count , const void * = 0 ) { return static_cast < pointer > ( mi_new_n ( count , sizeof ( value_type ) ) ) ; }
2020-01-22 18:33:07 -08:00
# endif
2020-01-20 15:27:05 -08:00
# if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
2022-11-24 15:13:19 +01:00
using is_always_equal = std : : true_type ;
2020-01-17 15:41:52 -08:00
# endif
2020-01-16 15:17:15 -08:00
} ;
2020-01-17 15:41:52 -08:00
template < class T1 , class T2 > bool operator = = ( const mi_stl_allocator < T1 > & , const mi_stl_allocator < T2 > & ) mi_attr_noexcept { return true ; }
template < class T1 , class T2 > bool operator ! = ( const mi_stl_allocator < T1 > & , const mi_stl_allocator < T2 > & ) mi_attr_noexcept { return false ; }
2022-11-22 16:58:32 -08:00
2022-11-27 13:00:15 -08:00
2023-03-15 20:31:52 -07:00
# if (__cplusplus >= 201103L) || (_MSC_VER >= 1900) // C++11
2023-02-07 11:07:52 -08:00
# define MI_HAS_HEAP_STL_ALLOCATOR 1
2022-11-22 16:58:32 -08:00
# include <memory> // std::shared_ptr
2022-11-27 13:00:15 -08:00
// Common base class for STL allocators in a specific heap
2023-03-15 20:31:52 -07:00
template < class T , bool _mi_destroy > struct _mi_heap_stl_allocator_common : public _mi_stl_allocator_common < T > {
2022-11-24 15:13:19 +01:00
using typename _mi_stl_allocator_common < T > : : size_type ;
2022-11-27 13:00:15 -08:00
using typename _mi_stl_allocator_common < T > : : value_type ;
using typename _mi_stl_allocator_common < T > : : pointer ;
2022-11-22 16:58:32 -08:00
2024-03-09 15:14:32 +01:00
_mi_heap_stl_allocator_common ( mi_heap_t * hp ) : heap ( hp , [ ] ( mi_heap_t * ) { } ) { } /* will not delete nor destroy the passed in heap */
2022-11-22 16:58:32 -08:00
# if (__cplusplus >= 201703L) // C++17
mi_decl_nodiscard T * allocate ( size_type count ) { return static_cast < T * > ( mi_heap_alloc_new_n ( this - > heap . get ( ) , count , sizeof ( T ) ) ) ; }
mi_decl_nodiscard T * allocate ( size_type count , const void * ) { return allocate ( count ) ; }
# else
mi_decl_nodiscard pointer allocate ( size_type count , const void * = 0 ) { return static_cast < pointer > ( mi_heap_alloc_new_n ( this - > heap . get ( ) , count , sizeof ( value_type ) ) ) ; }
# endif
# if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
using is_always_equal = std : : false_type ;
# endif
void collect ( bool force ) { mi_heap_collect ( this - > heap . get ( ) , force ) ; }
2023-03-15 20:31:52 -07:00
template < class U > bool is_equal ( const _mi_heap_stl_allocator_common < U , _mi_destroy > & x ) const { return ( this - > heap = = x . heap ) ; }
2022-11-22 16:58:32 -08:00
2022-11-24 15:13:19 +01:00
protected :
2022-11-22 16:58:32 -08:00
std : : shared_ptr < mi_heap_t > heap ;
2022-11-28 11:55:58 +01:00
template < class U , bool D > friend struct _mi_heap_stl_allocator_common ;
2024-03-01 15:15:24 -08:00
2022-11-28 11:55:58 +01:00
_mi_heap_stl_allocator_common ( ) {
2022-11-27 13:00:15 -08:00
mi_heap_t * hp = mi_heap_new ( ) ;
2023-03-15 20:31:52 -07:00
this - > heap . reset ( hp , ( _mi_destroy ? & heap_destroy : & heap_delete ) ) ; /* calls heap_delete/destroy when the refcount drops to zero */
2022-11-27 13:00:15 -08:00
}
_mi_heap_stl_allocator_common ( const _mi_heap_stl_allocator_common & x ) mi_attr_noexcept : heap ( x . heap ) { }
2023-03-15 20:31:52 -07:00
template < class U > _mi_heap_stl_allocator_common ( const _mi_heap_stl_allocator_common < U , _mi_destroy > & x ) mi_attr_noexcept : heap ( x . heap ) { }
2022-11-22 16:58:32 -08:00
private :
static void heap_delete ( mi_heap_t * hp ) { if ( hp ! = NULL ) { mi_heap_delete ( hp ) ; } }
2022-11-27 13:00:15 -08:00
static void heap_destroy ( mi_heap_t * hp ) { if ( hp ! = NULL ) { mi_heap_destroy ( hp ) ; } }
2022-11-22 16:58:32 -08:00
} ;
2022-11-24 15:13:19 +01:00
// STL allocator allocation in a specific heap
2022-11-28 11:55:58 +01:00
template < class T > struct mi_heap_stl_allocator : public _mi_heap_stl_allocator_common < T , false > {
using typename _mi_heap_stl_allocator_common < T , false > : : size_type ;
2022-12-19 17:25:49 -08:00
mi_heap_stl_allocator ( ) : _mi_heap_stl_allocator_common < T , false > ( ) { } // creates fresh heap that is deleted when the destructor is called
2024-03-01 15:15:24 -08:00
mi_heap_stl_allocator ( mi_heap_t * hp ) : _mi_heap_stl_allocator_common < T , false > ( hp ) { } // no delete nor destroy on the passed in heap
2022-11-28 11:55:58 +01:00
template < class U > mi_heap_stl_allocator ( const mi_heap_stl_allocator < U > & x ) mi_attr_noexcept : _mi_heap_stl_allocator_common < T , false > ( x ) { }
2022-11-24 15:13:19 +01:00
mi_heap_stl_allocator select_on_container_copy_construction ( ) const { return * this ; }
void deallocate ( T * p , size_type ) { mi_free ( p ) ; }
2022-11-27 13:00:15 -08:00
template < class U > struct rebind { typedef mi_heap_stl_allocator < U > other ; } ;
2022-11-22 16:58:32 -08:00
} ;
2022-11-27 13:00:15 -08:00
template < class T1 , class T2 > bool operator = = ( const mi_heap_stl_allocator < T1 > & x , const mi_heap_stl_allocator < T2 > & y ) mi_attr_noexcept { return ( x . is_equal ( y ) ) ; }
template < class T1 , class T2 > bool operator ! = ( const mi_heap_stl_allocator < T1 > & x , const mi_heap_stl_allocator < T2 > & y ) mi_attr_noexcept { return ( ! x . is_equal ( y ) ) ; }
2022-11-22 16:58:32 -08:00
2022-12-03 00:23:43 +01:00
// STL allocator allocation in a specific heap, where `free` does nothing and
2022-11-22 16:58:32 -08:00
// the heap is destroyed in one go on destruction -- use with care!
2022-11-28 11:55:58 +01:00
template < class T > struct mi_heap_destroy_stl_allocator : public _mi_heap_stl_allocator_common < T , true > {
using typename _mi_heap_stl_allocator_common < T , true > : : size_type ;
2022-12-19 17:25:49 -08:00
mi_heap_destroy_stl_allocator ( ) : _mi_heap_stl_allocator_common < T , true > ( ) { } // creates fresh heap that is destroyed when the destructor is called
2024-03-01 15:15:24 -08:00
mi_heap_destroy_stl_allocator ( mi_heap_t * hp ) : _mi_heap_stl_allocator_common < T , true > ( hp ) { } // no delete nor destroy on the passed in heap
2022-11-28 11:55:58 +01:00
template < class U > mi_heap_destroy_stl_allocator ( const mi_heap_destroy_stl_allocator < U > & x ) mi_attr_noexcept : _mi_heap_stl_allocator_common < T , true > ( x ) { }
2022-11-22 16:58:32 -08:00
2022-11-24 15:13:19 +01:00
mi_heap_destroy_stl_allocator select_on_container_copy_construction ( ) const { return * this ; }
2022-11-28 10:54:45 -08:00
void deallocate ( T * , size_type ) { /* do nothing as we destroy the heap on destruct. */ }
2022-11-27 13:00:15 -08:00
template < class U > struct rebind { typedef mi_heap_destroy_stl_allocator < U > other ; } ;
2022-11-22 16:58:32 -08:00
} ;
2022-11-27 13:00:15 -08:00
template < class T1 , class T2 > bool operator = = ( const mi_heap_destroy_stl_allocator < T1 > & x , const mi_heap_destroy_stl_allocator < T2 > & y ) mi_attr_noexcept { return ( x . is_equal ( y ) ) ; }
template < class T1 , class T2 > bool operator ! = ( const mi_heap_destroy_stl_allocator < T1 > & x , const mi_heap_destroy_stl_allocator < T2 > & y ) mi_attr_noexcept { return ( ! x . is_equal ( y ) ) ; }
2022-11-22 16:58:32 -08:00
# endif // C++11
2020-01-16 15:57:11 -08:00
# endif // __cplusplus
2019-07-07 18:11:21 -07:00
2019-06-19 16:26:12 -07:00
# endif