Free the thread local default heap (called from `mi_thread_done`)
| 295 | |
| 296 | // Free the thread local default heap (called from `mi_thread_done`) |
| 297 | static bool _mi_heap_done(mi_heap_t* heap) { |
| 298 | if (!mi_heap_is_initialized(heap)) return true; |
| 299 | |
| 300 | // reset default heap |
| 301 | _mi_heap_set_default_direct(_mi_is_main_thread() ? &_mi_heap_main : (mi_heap_t*)&_mi_heap_empty); |
| 302 | |
| 303 | // switch to backing heap |
| 304 | heap = heap->tld->heap_backing; |
| 305 | if (!mi_heap_is_initialized(heap)) return false; |
| 306 | |
| 307 | // delete all non-backing heaps in this thread |
| 308 | mi_heap_t* curr = heap->tld->heaps; |
| 309 | while (curr != NULL) { |
| 310 | mi_heap_t* next = curr->next; // save `next` as `curr` will be freed |
| 311 | if (curr != heap) { |
| 312 | mi_assert_internal(!mi_heap_is_backing(curr)); |
| 313 | mi_heap_delete(curr); |
| 314 | } |
| 315 | curr = next; |
| 316 | } |
| 317 | mi_assert_internal(heap->tld->heaps == heap && heap->next == NULL); |
| 318 | mi_assert_internal(mi_heap_is_backing(heap)); |
| 319 | |
| 320 | // collect if not the main thread |
| 321 | if (heap != &_mi_heap_main) { |
| 322 | _mi_heap_collect_abandon(heap); |
| 323 | } |
| 324 | |
| 325 | // merge stats |
| 326 | _mi_stats_done(&heap->tld->stats); |
| 327 | |
| 328 | // free if not the main thread |
| 329 | if (heap != &_mi_heap_main) { |
| 330 | // the following assertion does not always hold for huge segments as those are always treated |
| 331 | // as abondened: one may allocate it in one thread, but deallocate in another in which case |
| 332 | // the count can be too large or negative. todo: perhaps not count huge segments? see issue #363 |
| 333 | // mi_assert_internal(heap->tld->segments.count == 0 || heap->thread_id != _mi_thread_id()); |
| 334 | mi_thread_data_free((mi_thread_data_t*)heap); |
| 335 | } |
| 336 | else { |
| 337 | mi_thread_data_collect(); // free cached thread metadata |
| 338 | #if 0 |
| 339 | // never free the main thread even in debug mode; if a dll is linked statically with mimalloc, |
| 340 | // there may still be delete/free calls after the mi_fls_done is called. Issue #207 |
| 341 | _mi_heap_destroy_pages(heap); |
| 342 | mi_assert_internal(heap->tld->heap_backing == &_mi_heap_main); |
| 343 | #endif |
| 344 | } |
| 345 | return false; |
| 346 | } |
| 347 | |
| 348 | |
| 349 |
no test coverage detected