mimalloc.h 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
  2. /* ----------------------------------------------------------------------------
  3. Copyright (c) 2018-2026, Microsoft Research, Daan Leijen
  4. This is free software; you can redistribute it and/or modify it under the
  5. terms of the MIT license. A copy of the license can be found in the file
  6. "LICENSE" at the root of this distribution.
  7. -----------------------------------------------------------------------------*/
  8. #pragma once
  9. #ifndef MIMALLOC_H
  10. #define MIMALLOC_H
  11. #define MI_MALLOC_VERSION 226 // major + 2 digits minor
  12. // ------------------------------------------------------
  13. // Compiler specific attributes
  14. // ------------------------------------------------------
  15. #ifdef __cplusplus
  16. #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
  17. #define mi_attr_noexcept noexcept
  18. #else
  19. #define mi_attr_noexcept throw()
  20. #endif
  21. #else
  22. #define mi_attr_noexcept
  23. #endif
  24. #if defined(__cplusplus) && (__cplusplus >= 201703)
  25. #define mi_decl_nodiscard [[nodiscard]]
  26. #elif (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) // includes clang, icc, and clang-cl
  27. #define mi_decl_nodiscard __attribute__((warn_unused_result))
  28. #elif defined(_HAS_NODISCARD)
  29. #define mi_decl_nodiscard _NODISCARD
  30. #elif (_MSC_VER >= 1700)
  31. #define mi_decl_nodiscard _Check_return_
  32. #else
  33. #define mi_decl_nodiscard
  34. #endif
  35. #if defined(_MSC_VER) || defined(__MINGW32__)
  36. #if !defined(MI_SHARED_LIB)
  37. #define mi_decl_export
  38. #elif defined(MI_SHARED_LIB_EXPORT)
  39. #define mi_decl_export __declspec(dllexport)
  40. #else
  41. #define mi_decl_export __declspec(dllimport)
  42. #endif
  43. #if defined(__MINGW32__)
  44. #define mi_decl_restrict
  45. #define mi_attr_malloc __attribute__((malloc))
  46. #else
  47. #if (_MSC_VER >= 1900) && !defined(__EDG__)
  48. #define mi_decl_restrict __declspec(allocator) __declspec(restrict)
  49. #else
  50. #define mi_decl_restrict __declspec(restrict)
  51. #endif
  52. #define mi_attr_malloc
  53. #endif
  54. #define mi_cdecl __cdecl
  55. #define mi_attr_alloc_size(s)
  56. #define mi_attr_alloc_size2(s1,s2)
  57. #define mi_attr_alloc_align(p)
  58. #elif defined(__GNUC__) // includes clang and icc
  59. #if defined(MI_SHARED_LIB) && defined(MI_SHARED_LIB_EXPORT)
  60. #define mi_decl_export __attribute__((visibility("default")))
  61. #else
  62. #define mi_decl_export
  63. #endif
  64. #define mi_cdecl // leads to warnings... __attribute__((cdecl))
  65. #define mi_decl_restrict
  66. #define mi_attr_malloc __attribute__((malloc))
  67. #if (defined(__clang_major__) && (__clang_major__ < 4)) || (__GNUC__ < 5)
  68. #define mi_attr_alloc_size(s)
  69. #define mi_attr_alloc_size2(s1,s2)
  70. #define mi_attr_alloc_align(p)
  71. #elif defined(__INTEL_COMPILER)
  72. #define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
  73. #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
  74. #define mi_attr_alloc_align(p)
  75. #else
  76. #define mi_attr_alloc_size(s) __attribute__((alloc_size(s)))
  77. #define mi_attr_alloc_size2(s1,s2) __attribute__((alloc_size(s1,s2)))
  78. #define mi_attr_alloc_align(p) __attribute__((alloc_align(p)))
  79. #endif
  80. #else
  81. #define mi_cdecl
  82. #define mi_decl_export
  83. #define mi_decl_restrict
  84. #define mi_attr_malloc
  85. #define mi_attr_alloc_size(s)
  86. #define mi_attr_alloc_size2(s1,s2)
  87. #define mi_attr_alloc_align(p)
  88. #endif
  89. // ------------------------------------------------------
  90. // Includes
  91. // ------------------------------------------------------
  92. #include <stddef.h> // size_t
  93. #include <stdbool.h> // bool
  94. #include <stdint.h> // INTPTR_MAX
  95. #ifdef __cplusplus
  96. extern "C" {
  97. #endif
  98. // ------------------------------------------------------
  99. // Standard malloc interface
  100. // ------------------------------------------------------
  101. 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);
  102. 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);
  103. mi_decl_nodiscard mi_decl_export void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  104. mi_decl_export void* mi_expand(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  105. mi_decl_export void mi_free(void* p) mi_attr_noexcept;
  106. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept mi_attr_malloc;
  107. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept mi_attr_malloc;
  108. mi_decl_nodiscard mi_decl_export mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept mi_attr_malloc;
  109. // ------------------------------------------------------
  110. // Extended functionality
  111. // ------------------------------------------------------
  112. #define MI_SMALL_WSIZE_MAX (128)
  113. #define MI_SMALL_SIZE_MAX (MI_SMALL_WSIZE_MAX*sizeof(void*))
  114. 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);
  115. 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);
  116. 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);
  117. 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);
  118. 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);
  119. mi_decl_nodiscard mi_decl_export void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  120. mi_decl_nodiscard mi_decl_export size_t mi_usable_size(const void* p) mi_attr_noexcept;
  121. mi_decl_nodiscard mi_decl_export size_t mi_good_size(size_t size) mi_attr_noexcept;
  122. // ------------------------------------------------------
  123. // Internals
  124. // ------------------------------------------------------
  125. typedef void (mi_cdecl mi_deferred_free_fun)(bool force, unsigned long long heartbeat, void* arg);
  126. mi_decl_export void mi_register_deferred_free(mi_deferred_free_fun* deferred_free, void* arg) mi_attr_noexcept;
  127. typedef void (mi_cdecl mi_output_fun)(const char* msg, void* arg);
  128. mi_decl_export void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept;
  129. typedef void (mi_cdecl mi_error_fun)(int err, void* arg);
  130. mi_decl_export void mi_register_error(mi_error_fun* fun, void* arg);
  131. mi_decl_export void mi_collect(bool force) mi_attr_noexcept;
  132. mi_decl_export int mi_version(void) mi_attr_noexcept;
  133. mi_decl_export void mi_stats_reset(void) mi_attr_noexcept;
  134. mi_decl_export void mi_stats_merge(void) mi_attr_noexcept;
  135. mi_decl_export void mi_stats_print(void* out) mi_attr_noexcept; // backward compatibility: `out` is ignored and should be NULL
  136. mi_decl_export void mi_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
  137. mi_decl_export void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept;
  138. mi_decl_export void mi_options_print(void) mi_attr_noexcept;
  139. mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs,
  140. size_t* current_rss, size_t* peak_rss,
  141. size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept;
  142. // Generally do not use the following as these are usually called automatically
  143. mi_decl_export void mi_process_init(void) mi_attr_noexcept;
  144. mi_decl_export void mi_cdecl mi_process_done(void) mi_attr_noexcept;
  145. mi_decl_export void mi_thread_init(void) mi_attr_noexcept;
  146. mi_decl_export void mi_thread_done(void) mi_attr_noexcept;
  147. // -------------------------------------------------------------------------------------
  148. // Aligned allocation
  149. // Note that `alignment` always follows `size` for consistency with unaligned
  150. // allocation, but unfortunately this differs from `posix_memalign` and `aligned_alloc`.
  151. // -------------------------------------------------------------------------------------
  152. 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);
  153. 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);
  154. 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);
  155. 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);
  156. 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);
  157. 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);
  158. 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);
  159. 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);
  160. // -----------------------------------------------------------------
  161. // Return allocated block size (if the return value is not NULL)
  162. // -----------------------------------------------------------------
  163. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_umalloc(size_t size, size_t* block_size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  164. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_ucalloc(size_t count, size_t size, size_t* block_size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size2(1,2);
  165. mi_decl_nodiscard mi_decl_export void* mi_urealloc(void* p, size_t newsize, size_t* block_size_pre, size_t* block_size_post) mi_attr_noexcept mi_attr_alloc_size(2);
  166. mi_decl_export void mi_ufree(void* p, size_t* block_size) mi_attr_noexcept;
  167. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_umalloc_aligned(size_t size, size_t alignment, size_t* block_size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
  168. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_uzalloc_aligned(size_t size, size_t alignment, size_t* block_size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1) mi_attr_alloc_align(2);
  169. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_umalloc_small(size_t size, size_t* block_size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  170. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_uzalloc_small(size_t size, size_t* block_size) mi_attr_noexcept mi_attr_malloc mi_attr_alloc_size(1);
  171. // -------------------------------------------------------------------------------------
  172. // Heaps: first-class, but can only allocate from the same thread that created it.
  173. // -------------------------------------------------------------------------------------
  174. struct mi_heap_s;
  175. typedef struct mi_heap_s mi_heap_t;
  176. mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new(void);
  177. mi_decl_export void mi_heap_delete(mi_heap_t* heap);
  178. mi_decl_export void mi_heap_destroy(mi_heap_t* heap);
  179. mi_decl_export mi_heap_t* mi_heap_set_default(mi_heap_t* heap);
  180. mi_decl_export mi_heap_t* mi_heap_get_default(void);
  181. mi_decl_export mi_heap_t* mi_heap_get_backing(void);
  182. mi_decl_export void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept;
  183. 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);
  184. 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);
  185. 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);
  186. 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);
  187. 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);
  188. 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);
  189. 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);
  190. 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);
  191. 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;
  192. 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;
  193. 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;
  194. 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);
  195. 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);
  196. 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);
  197. 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);
  198. 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);
  199. 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);
  200. 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);
  201. 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);
  202. // --------------------------------------------------------------------------------
  203. // Zero initialized re-allocation.
  204. // Only valid on memory that was originally allocated with zero initialization too.
  205. // e.g. `mi_calloc`, `mi_zalloc`, `mi_zalloc_aligned` etc.
  206. // see <https://github.com/microsoft/mimalloc/issues/63#issuecomment-508272992>
  207. // --------------------------------------------------------------------------------
  208. mi_decl_nodiscard mi_decl_export void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept mi_attr_alloc_size(2);
  209. 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);
  210. 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);
  211. 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);
  212. 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);
  213. 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);
  214. 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);
  215. 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);
  216. 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);
  217. 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);
  218. 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);
  219. 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);
  220. // ------------------------------------------------------
  221. // Analysis
  222. // ------------------------------------------------------
  223. mi_decl_export bool mi_heap_contains_block(mi_heap_t* heap, const void* p);
  224. mi_decl_export bool mi_heap_check_owned(mi_heap_t* heap, const void* p);
  225. mi_decl_export bool mi_check_owned(const void* p);
  226. // An area of heap space contains blocks of a single size.
  227. typedef struct mi_heap_area_s {
  228. void* blocks; // start of the area containing heap blocks
  229. size_t reserved; // bytes reserved for this area (virtual)
  230. size_t committed; // current available bytes for this area
  231. size_t used; // number of allocated blocks
  232. size_t block_size; // size in bytes of each block
  233. size_t full_block_size; // size in bytes of a full block including padding and metadata.
  234. int heap_tag; // heap tag associated with this area
  235. } mi_heap_area_t;
  236. 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);
  237. mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_blocks, mi_block_visit_fun* visitor, void* arg);
  238. // Experimental
  239. mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_attr_noexcept;
  240. mi_decl_nodiscard mi_decl_export bool mi_is_redirected(void) mi_attr_noexcept;
  241. mi_decl_export int mi_reserve_huge_os_pages_interleave(size_t pages, size_t numa_nodes, size_t timeout_msecs) mi_attr_noexcept;
  242. mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size_t timeout_msecs) mi_attr_noexcept;
  243. mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
  244. 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;
  245. mi_decl_export void mi_debug_show_arenas(void) mi_attr_noexcept;
  246. mi_decl_export void mi_arenas_print(void) mi_attr_noexcept;
  247. // Experimental: heaps associated with specific memory arena's
  248. typedef int mi_arena_id_t;
  249. mi_decl_export void* mi_arena_area(mi_arena_id_t arena_id, size_t* size);
  250. 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;
  251. 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;
  252. 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;
  253. #if MI_MALLOC_VERSION >= 182
  254. // Create a heap that only allocates in the specified arena
  255. mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t arena_id);
  256. #endif
  257. // Experimental: allow sub-processes whose memory areas stay separated (and no reclamation between them)
  258. // Used for example for separate interpreters in one process.
  259. typedef void* mi_subproc_id_t;
  260. mi_decl_export mi_subproc_id_t mi_subproc_main(void);
  261. mi_decl_export mi_subproc_id_t mi_subproc_new(void);
  262. mi_decl_export void mi_subproc_delete(mi_subproc_id_t subproc);
  263. mi_decl_export void mi_subproc_add_current_thread(mi_subproc_id_t subproc); // this should be called right after a thread is created (and no allocation has taken place yet)
  264. // Experimental: visit abandoned heap areas (that are not owned by a specific heap)
  265. mi_decl_export bool mi_abandoned_visit_blocks(mi_subproc_id_t subproc_id, int heap_tag, bool visit_blocks, mi_block_visit_fun* visitor, void* arg);
  266. // Experimental: objects followed by a guard page.
  267. // A sample rate of 0 disables guarded objects, while 1 uses a guard page for every object.
  268. // A seed of 0 uses a random start point. Only objects within the size bound are eligable for guard pages.
  269. mi_decl_export void mi_heap_guarded_set_sample_rate(mi_heap_t* heap, size_t sample_rate, size_t seed);
  270. mi_decl_export void mi_heap_guarded_set_size_bound(mi_heap_t* heap, size_t min, size_t max);
  271. // Experimental: communicate that the thread is part of a threadpool
  272. mi_decl_export void mi_thread_set_in_threadpool(void) mi_attr_noexcept;
  273. // Experimental: create a new heap with a specified heap tag. Set `allow_destroy` to false to allow the thread
  274. // to reclaim abandoned memory (with a compatible heap_tag and arena_id) but in that case `mi_heap_destroy` will
  275. // fall back to `mi_heap_delete`.
  276. mi_decl_nodiscard mi_decl_export mi_heap_t* mi_heap_new_ex(int heap_tag, bool allow_destroy, mi_arena_id_t arena_id);
  277. // deprecated
  278. mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
  279. mi_decl_export void mi_collect_reduce(size_t target_thread_owned) mi_attr_noexcept;
  280. // ------------------------------------------------------
  281. // Convenience
  282. // ------------------------------------------------------
  283. #define mi_malloc_tp(tp) ((tp*)mi_malloc(sizeof(tp)))
  284. #define mi_zalloc_tp(tp) ((tp*)mi_zalloc(sizeof(tp)))
  285. #define mi_calloc_tp(tp,n) ((tp*)mi_calloc(n,sizeof(tp)))
  286. #define mi_mallocn_tp(tp,n) ((tp*)mi_mallocn(n,sizeof(tp)))
  287. #define mi_reallocn_tp(p,tp,n) ((tp*)mi_reallocn(p,n,sizeof(tp)))
  288. #define mi_recalloc_tp(p,tp,n) ((tp*)mi_recalloc(p,n,sizeof(tp)))
  289. #define mi_heap_malloc_tp(hp,tp) ((tp*)mi_heap_malloc(hp,sizeof(tp)))
  290. #define mi_heap_zalloc_tp(hp,tp) ((tp*)mi_heap_zalloc(hp,sizeof(tp)))
  291. #define mi_heap_calloc_tp(hp,tp,n) ((tp*)mi_heap_calloc(hp,n,sizeof(tp)))
  292. #define mi_heap_mallocn_tp(hp,tp,n) ((tp*)mi_heap_mallocn(hp,n,sizeof(tp)))
  293. #define mi_heap_reallocn_tp(hp,p,tp,n) ((tp*)mi_heap_reallocn(hp,p,n,sizeof(tp)))
  294. #define mi_heap_recalloc_tp(hp,p,tp,n) ((tp*)mi_heap_recalloc(hp,p,n,sizeof(tp)))
  295. // ------------------------------------------------------
  296. // Options
  297. // ------------------------------------------------------
  298. typedef enum mi_option_e {
  299. // stable options
  300. mi_option_show_errors, // print error messages
  301. mi_option_show_stats, // print statistics on termination
  302. mi_option_verbose, // print verbose messages
  303. // advanced options
  304. mi_option_eager_commit, // eager commit segments? (after `eager_commit_delay` segments) (=1)
  305. mi_option_arena_eager_commit, // eager commit arenas? Use 2 to enable just on overcommit systems (=2)
  306. mi_option_purge_decommits, // should a memory purge decommit? (=1). Set to 0 to use memory reset on a purge (instead of decommit)
  307. mi_option_allow_large_os_pages, // allow use of large (2 or 4 MiB) OS pages, implies eager commit.
  308. mi_option_reserve_huge_os_pages, // reserve N huge OS pages (1GiB pages) at startup
  309. mi_option_reserve_huge_os_pages_at, // reserve huge OS pages at a specific NUMA node
  310. 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`)
  311. mi_option_deprecated_segment_cache,
  312. mi_option_deprecated_page_reset,
  313. mi_option_abandoned_page_purge, // immediately purge delayed purges on thread termination
  314. mi_option_deprecated_segment_reset,
  315. mi_option_eager_commit_delay, // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
  316. 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)
  317. mi_option_use_numa_nodes, // 0 = use all available numa nodes, otherwise use at most N nodes.
  318. mi_option_disallow_os_alloc, // 1 = do not use OS memory for allocation (but only programmatically reserved arenas)
  319. mi_option_os_tag, // tag used for OS logging (macOS only for now) (=100)
  320. mi_option_max_errors, // issue at most N error messages
  321. mi_option_max_warnings, // issue at most N warning messages
  322. mi_option_max_segment_reclaim, // max. percentage of the abandoned segments can be reclaimed per try (=10%)
  323. mi_option_destroy_on_exit, // if set, release all memory on exit; sometimes used for dynamic unloading but can be unsafe
  324. 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`)
  325. mi_option_arena_purge_mult, // multiplier for `purge_delay` for the purging delay for arenas (=10)
  326. mi_option_purge_extend_delay,
  327. mi_option_abandoned_reclaim_on_free, // allow to reclaim an abandoned segment on a free (=1)
  328. mi_option_disallow_arena_alloc, // 1 = do not use arena's for allocation (except if using specific arena id's)
  329. mi_option_retry_on_oom, // retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries. (only on windows)
  330. mi_option_visit_abandoned, // allow visiting heap blocks from abandoned threads (=0)
  331. mi_option_guarded_min, // only used when building with MI_GUARDED: minimal rounded object size for guarded objects (=0)
  332. mi_option_guarded_max, // only used when building with MI_GUARDED: maximal rounded object size for guarded objects (=0)
  333. mi_option_guarded_precise, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0)
  334. mi_option_guarded_sample_rate, // 1 out of N allocations in the min/max range will be guarded (=1000)
  335. mi_option_guarded_sample_seed, // can be set to allow for a (more) deterministic re-execution when a guard page is triggered (=0)
  336. mi_option_target_segments_per_thread, // experimental (=0)
  337. mi_option_generic_collect, // collect heaps every N (=10000) generic allocation calls
  338. mi_option_allow_thp, // allow transparent huge pages? (=1) (on Android =0 by default). Set to 0 to disable THP for the process.
  339. _mi_option_last,
  340. // legacy option names
  341. mi_option_large_os_pages = mi_option_allow_large_os_pages,
  342. mi_option_eager_region_commit = mi_option_arena_eager_commit,
  343. mi_option_reset_decommits = mi_option_purge_decommits,
  344. mi_option_reset_delay = mi_option_purge_delay,
  345. mi_option_abandoned_page_reset = mi_option_abandoned_page_purge,
  346. mi_option_limit_os_alloc = mi_option_disallow_os_alloc
  347. } mi_option_t;
  348. mi_decl_nodiscard mi_decl_export bool mi_option_is_enabled(mi_option_t option);
  349. mi_decl_export void mi_option_enable(mi_option_t option);
  350. mi_decl_export void mi_option_disable(mi_option_t option);
  351. mi_decl_export void mi_option_set_enabled(mi_option_t option, bool enable);
  352. mi_decl_export void mi_option_set_enabled_default(mi_option_t option, bool enable);
  353. mi_decl_nodiscard mi_decl_export long mi_option_get(mi_option_t option);
  354. mi_decl_nodiscard mi_decl_export long mi_option_get_clamp(mi_option_t option, long min, long max);
  355. mi_decl_nodiscard mi_decl_export size_t mi_option_get_size(mi_option_t option);
  356. mi_decl_export void mi_option_set(mi_option_t option, long value);
  357. mi_decl_export void mi_option_set_default(mi_option_t option, long value);
  358. // -------------------------------------------------------------------------------------------------------
  359. // "mi" prefixed implementations of various posix, Unix, Windows, and C++ allocation functions.
  360. // (This can be convenient when providing overrides of these functions as done in `mimalloc-override.h`.)
  361. // note: we use `mi_cfree` as "checked free" and it checks if the pointer is in our heap before free-ing.
  362. // -------------------------------------------------------------------------------------------------------
  363. mi_decl_export void mi_cfree(void* p) mi_attr_noexcept;
  364. mi_decl_export void* mi__expand(void* p, size_t newsize) mi_attr_noexcept;
  365. mi_decl_nodiscard mi_decl_export size_t mi_malloc_size(const void* p) mi_attr_noexcept;
  366. mi_decl_nodiscard mi_decl_export size_t mi_malloc_good_size(size_t size) mi_attr_noexcept;
  367. mi_decl_nodiscard mi_decl_export size_t mi_malloc_usable_size(const void *p) mi_attr_noexcept;
  368. mi_decl_export int mi_posix_memalign(void** p, size_t alignment, size_t size) mi_attr_noexcept;
  369. 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);
  370. 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);
  371. 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);
  372. 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);
  373. 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);
  374. mi_decl_nodiscard mi_decl_export int mi_reallocarr(void* p, size_t count, size_t size) mi_attr_noexcept;
  375. mi_decl_nodiscard mi_decl_export void* mi_aligned_recalloc(void* p, size_t newcount, size_t size, size_t alignment) mi_attr_noexcept;
  376. 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;
  377. mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned short* mi_wcsdup(const unsigned short* s) mi_attr_noexcept mi_attr_malloc;
  378. mi_decl_nodiscard mi_decl_export mi_decl_restrict unsigned char* mi_mbsdup(const unsigned char* s) mi_attr_noexcept mi_attr_malloc;
  379. mi_decl_export int mi_dupenv_s(char** buf, size_t* size, const char* name) mi_attr_noexcept;
  380. mi_decl_export int mi_wdupenv_s(unsigned short** buf, size_t* size, const unsigned short* name) mi_attr_noexcept;
  381. mi_decl_export void mi_free_size(void* p, size_t size) mi_attr_noexcept;
  382. mi_decl_export void mi_free_size_aligned(void* p, size_t size, size_t alignment) mi_attr_noexcept;
  383. mi_decl_export void mi_free_aligned(void* p, size_t alignment) mi_attr_noexcept;
  384. // The `mi_new` wrappers implement C++ semantics on out-of-memory instead of directly returning `NULL`.
  385. // (and call `std::get_new_handler` and potentially raise a `std::bad_alloc` exception).
  386. mi_decl_nodiscard mi_decl_export mi_decl_restrict void* mi_new(size_t size) mi_attr_malloc mi_attr_alloc_size(1);
  387. 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);
  388. 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);
  389. 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);
  390. 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);
  391. mi_decl_nodiscard mi_decl_export void* mi_new_realloc(void* p, size_t newsize) mi_attr_alloc_size(2);
  392. mi_decl_nodiscard mi_decl_export void* mi_new_reallocn(void* p, size_t newcount, size_t size) mi_attr_alloc_size2(2, 3);
  393. 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);
  394. 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);
  395. #ifdef __cplusplus
  396. }
  397. #endif
  398. // ---------------------------------------------------------------------------------------------
  399. // Implement the C++ std::allocator interface for use in STL containers.
  400. // (note: see `mimalloc-new-delete.h` for overriding the new/delete operators globally)
  401. // ---------------------------------------------------------------------------------------------
  402. #ifdef __cplusplus
  403. #include <cstddef> // std::size_t
  404. #include <cstdint> // PTRDIFF_MAX
  405. #if (__cplusplus >= 201103L) || (_MSC_VER > 1900) // C++11
  406. #include <type_traits> // std::true_type
  407. #include <utility> // std::forward
  408. #endif
  409. template<class T> struct _mi_stl_allocator_common {
  410. typedef T value_type;
  411. typedef std::size_t size_type;
  412. typedef std::ptrdiff_t difference_type;
  413. typedef value_type& reference;
  414. typedef value_type const& const_reference;
  415. typedef value_type* pointer;
  416. typedef value_type const* const_pointer;
  417. #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
  418. using propagate_on_container_copy_assignment = std::true_type;
  419. using propagate_on_container_move_assignment = std::true_type;
  420. using propagate_on_container_swap = std::true_type;
  421. template <class U, class ...Args> void construct(U* p, Args&& ...args) { ::new(p) U(std::forward<Args>(args)...); }
  422. template <class U> void destroy(U* p) mi_attr_noexcept { p->~U(); }
  423. #else
  424. void construct(pointer p, value_type const& val) { ::new(p) value_type(val); }
  425. void destroy(pointer p) { p->~value_type(); }
  426. #endif
  427. size_type max_size() const mi_attr_noexcept { return (PTRDIFF_MAX/sizeof(value_type)); }
  428. pointer address(reference x) const { return &x; }
  429. const_pointer address(const_reference x) const { return &x; }
  430. };
  431. template<class T> struct mi_stl_allocator : public _mi_stl_allocator_common<T> {
  432. using typename _mi_stl_allocator_common<T>::size_type;
  433. using typename _mi_stl_allocator_common<T>::value_type;
  434. using typename _mi_stl_allocator_common<T>::pointer;
  435. template <class U> struct rebind { typedef mi_stl_allocator<U> other; };
  436. mi_stl_allocator() mi_attr_noexcept = default;
  437. mi_stl_allocator(const mi_stl_allocator&) mi_attr_noexcept = default;
  438. template<class U> mi_stl_allocator(const mi_stl_allocator<U>&) mi_attr_noexcept { }
  439. mi_stl_allocator select_on_container_copy_construction() const { return *this; }
  440. void deallocate(T* p, size_type) { mi_free(p); }
  441. #if (__cplusplus >= 201703L) // C++17
  442. mi_decl_nodiscard T* allocate(size_type count) { return static_cast<T*>(mi_new_n(count, sizeof(T))); }
  443. mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); }
  444. #else
  445. mi_decl_nodiscard pointer allocate(size_type count, const void* = 0) { return static_cast<pointer>(mi_new_n(count, sizeof(value_type))); }
  446. #endif
  447. #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
  448. using is_always_equal = std::true_type;
  449. #endif
  450. };
  451. template<class T1,class T2> bool operator==(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return true; }
  452. template<class T1,class T2> bool operator!=(const mi_stl_allocator<T1>& , const mi_stl_allocator<T2>& ) mi_attr_noexcept { return false; }
  453. #if (__cplusplus >= 201103L) || (_MSC_VER >= 1900) // C++11
  454. #define MI_HAS_HEAP_STL_ALLOCATOR 1
  455. #include <memory> // std::shared_ptr
  456. // Common base class for STL allocators in a specific heap
  457. template<class T, bool _mi_destroy> struct _mi_heap_stl_allocator_common : public _mi_stl_allocator_common<T> {
  458. using typename _mi_stl_allocator_common<T>::size_type;
  459. using typename _mi_stl_allocator_common<T>::value_type;
  460. using typename _mi_stl_allocator_common<T>::pointer;
  461. _mi_heap_stl_allocator_common(mi_heap_t* hp) : heap(hp, [](mi_heap_t*) {}) {} /* will not delete nor destroy the passed in heap */
  462. #if (__cplusplus >= 201703L) // C++17
  463. mi_decl_nodiscard T* allocate(size_type count) { return static_cast<T*>(mi_heap_alloc_new_n(this->heap.get(), count, sizeof(T))); }
  464. mi_decl_nodiscard T* allocate(size_type count, const void*) { return allocate(count); }
  465. #else
  466. 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))); }
  467. #endif
  468. #if ((__cplusplus >= 201103L) || (_MSC_VER > 1900)) // C++11
  469. using is_always_equal = std::false_type;
  470. #endif
  471. void collect(bool force) { mi_heap_collect(this->heap.get(), force); }
  472. template<class U> bool is_equal(const _mi_heap_stl_allocator_common<U, _mi_destroy>& x) const { return (this->heap == x.heap); }
  473. protected:
  474. std::shared_ptr<mi_heap_t> heap;
  475. template<class U, bool D> friend struct _mi_heap_stl_allocator_common;
  476. _mi_heap_stl_allocator_common() {
  477. mi_heap_t* hp = mi_heap_new();
  478. this->heap.reset(hp, (_mi_destroy ? &heap_destroy : &heap_delete)); /* calls heap_delete/destroy when the refcount drops to zero */
  479. }
  480. _mi_heap_stl_allocator_common(const _mi_heap_stl_allocator_common& x) mi_attr_noexcept : heap(x.heap) { }
  481. template<class U> _mi_heap_stl_allocator_common(const _mi_heap_stl_allocator_common<U, _mi_destroy>& x) mi_attr_noexcept : heap(x.heap) { }
  482. private:
  483. static void heap_delete(mi_heap_t* hp) { if (hp != NULL) { mi_heap_delete(hp); } }
  484. static void heap_destroy(mi_heap_t* hp) { if (hp != NULL) { mi_heap_destroy(hp); } }
  485. };
  486. // STL allocator allocation in a specific heap
  487. template<class T> struct mi_heap_stl_allocator : public _mi_heap_stl_allocator_common<T, false> {
  488. using typename _mi_heap_stl_allocator_common<T, false>::size_type;
  489. mi_heap_stl_allocator() : _mi_heap_stl_allocator_common<T, false>() { } // creates fresh heap that is deleted when the destructor is called
  490. 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
  491. 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) { }
  492. mi_heap_stl_allocator select_on_container_copy_construction() const { return *this; }
  493. void deallocate(T* p, size_type) { mi_free(p); }
  494. template<class U> struct rebind { typedef mi_heap_stl_allocator<U> other; };
  495. };
  496. 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)); }
  497. 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)); }
  498. // STL allocator allocation in a specific heap, where `free` does nothing and
  499. // the heap is destroyed in one go on destruction -- use with care!
  500. template<class T> struct mi_heap_destroy_stl_allocator : public _mi_heap_stl_allocator_common<T, true> {
  501. using typename _mi_heap_stl_allocator_common<T, true>::size_type;
  502. mi_heap_destroy_stl_allocator() : _mi_heap_stl_allocator_common<T, true>() { } // creates fresh heap that is destroyed when the destructor is called
  503. 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
  504. 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) { }
  505. mi_heap_destroy_stl_allocator select_on_container_copy_construction() const { return *this; }
  506. void deallocate(T*, size_type) { /* do nothing as we destroy the heap on destruct. */ }
  507. template<class U> struct rebind { typedef mi_heap_destroy_stl_allocator<U> other; };
  508. };
  509. 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)); }
  510. 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)); }
  511. #endif // C++11
  512. #endif // __cplusplus
  513. #endif
  514. #else
  515. #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
  516. #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)