Transfer the pages from one heap to the other
| 368 | |
| 369 | // Transfer the pages from one heap to the other |
| 370 | static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) { |
| 371 | mi_assert_internal(heap!=NULL); |
| 372 | if (from==NULL || from->page_count == 0) return; |
| 373 | |
| 374 | // reduce the size of the delayed frees |
| 375 | _mi_heap_delayed_free_partial(from); |
| 376 | |
| 377 | // transfer all pages by appending the queues; this will set a new heap field |
| 378 | // so threads may do delayed frees in either heap for a while. |
| 379 | // note: appending waits for each page to not be in the `MI_DELAYED_FREEING` state |
| 380 | // so after this only the new heap will get delayed frees |
| 381 | for (size_t i = 0; i <= MI_BIN_FULL; i++) { |
| 382 | mi_page_queue_t* pq = &heap->pages[i]; |
| 383 | mi_page_queue_t* append = &from->pages[i]; |
| 384 | size_t pcount = _mi_page_queue_append(heap, pq, append); |
| 385 | heap->page_count += pcount; |
| 386 | from->page_count -= pcount; |
| 387 | } |
| 388 | mi_assert_internal(from->page_count == 0); |
| 389 | |
| 390 | // and do outstanding delayed frees in the `from` heap |
| 391 | // note: be careful here as the `heap` field in all those pages no longer point to `from`, |
| 392 | // turns out to be ok as `_mi_heap_delayed_free` only visits the list and calls a |
| 393 | // the regular `_mi_free_delayed_block` which is safe. |
| 394 | _mi_heap_delayed_free_all(from); |
| 395 | #if !defined(_MSC_VER) || (_MSC_VER > 1900) // somehow the following line gives an error in VS2015, issue #353 |
| 396 | mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_block_t,&from->thread_delayed_free) == NULL); |
| 397 | #endif |
| 398 | |
| 399 | // and reset the `from` heap |
| 400 | mi_heap_reset_pages(from); |
| 401 | } |
| 402 | |
| 403 | // Safe delete a heap without freeing any still allocated blocks in that heap. |
| 404 | void mi_heap_delete(mi_heap_t* heap) |
no test coverage detected