Replace {Alloc,FreeAll}Temporary() with mimalloc

The heaps are wrapped in a RAIIish thread_local handler,
since being affined affined to a single thread for allocations is
required by the API

Ref: #642
pull/649/head
наб 2020-07-09 15:27:35 +02:00 committed by whitequark
parent cbac182edf
commit c4ca4be91e
1 changed files with 19 additions and 50 deletions

View File

@ -10,6 +10,7 @@
# include <CoreFoundation/CFBundle.h> # include <CoreFoundation/CFBundle.h>
#endif #endif
#include "solvespace.h" #include "solvespace.h"
#include "mimalloc.h"
#include "config.h" #include "config.h"
#if defined(WIN32) #if defined(WIN32)
// Conversely, include Microsoft headers after solvespace.h to avoid clashes. // Conversely, include Microsoft headers after solvespace.h to avoid clashes.
@ -18,7 +19,6 @@
#else #else
# include <unistd.h> # include <unistd.h>
# include <sys/stat.h> # include <sys/stat.h>
# include <mutex>
#endif #endif
namespace SolveSpace { namespace SolveSpace {
@ -680,64 +680,33 @@ void DebugPrint(const char *fmt, ...) {
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Temporary arena, on Windows. // Temporary arena.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#if defined(WIN32) struct MimallocHeap {
mi_heap_t *heap = mi_heap_new();
static HANDLE TempArena = NULL; MimallocHeap() {
ssassert(heap != NULL, "out of memory");
}
void *AllocTemporary(size_t size) ~MimallocHeap() {
{ mi_heap_destroy(heap);
if(!TempArena) }
TempArena = HeapCreate(0, 0, 0); };
void *ptr = HeapAlloc(TempArena, HEAP_ZERO_MEMORY, size);
static thread_local MimallocHeap TempArena;
void *AllocTemporary(size_t size) {
void *ptr = mi_heap_zalloc(TempArena.heap, size);
ssassert(ptr != NULL, "out of memory"); ssassert(ptr != NULL, "out of memory");
return ptr; return ptr;
} }
void FreeAllTemporary() void FreeAllTemporary() {
{ MimallocHeap temp;
HeapDestroy(TempArena); std::swap(TempArena.heap, temp.heap);
TempArena = NULL;
} }
#endif
//-----------------------------------------------------------------------------
// Temporary arena, on Linux.
//-----------------------------------------------------------------------------
#if !defined(WIN32)
struct ArenaChunk {
ArenaChunk *next;
};
static std::mutex TempArenaMutex;
static ArenaChunk *TempArena = NULL;
void *AllocTemporary(size_t size)
{
ArenaChunk *chunk = (ArenaChunk *)calloc(1, sizeof(ArenaChunk) + size);
ssassert(chunk != NULL, "out of memory");
std::lock_guard<std::mutex> guard(TempArenaMutex);
chunk->next = TempArena;
TempArena = chunk;
return (void *)(chunk + 1);
}
void FreeAllTemporary()
{
std::lock_guard<std::mutex> guard(TempArenaMutex);
while(TempArena) {
ArenaChunk *chunk = TempArena;
TempArena = TempArena->next;
free(chunk);
}
}
#endif
} }
} }