diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4834a655..d1d9fc35 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,14 +26,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in # platform utilities -if(WIN32) - set(util_SOURCES - platform/utilwin.cpp) -else() - set(util_SOURCES - platform/utilunix.cpp) -endif() - if(APPLE) set(util_LIBRARIES ${APPKIT_LIBRARY}) diff --git a/src/lib.cpp b/src/lib.cpp index d1d54ff7..b0d8e1d6 100644 --- a/src/lib.cpp +++ b/src/lib.cpp @@ -67,9 +67,6 @@ void Slvs_MakeQuaternion(double ux, double uy, double uz, void Slvs_Solve(Slvs_System *ssys, Slvs_hGroup shg) { - // Create the temporary heap, if this is the first time we're solving. - FreeAllTemporary(); - int i; for(i = 0; i < ssys->params; i++) { Slvs_Param *sp = &(ssys->param[i]); diff --git a/src/platform/platform.cpp b/src/platform/platform.cpp index 974cce62..a1d29ea8 100644 --- a/src/platform/platform.cpp +++ b/src/platform/platform.cpp @@ -18,6 +18,7 @@ #else # include # include +# include #endif namespace SolveSpace { @@ -605,9 +606,6 @@ std::vector InitCli(int argc, char **argv) { } #endif - // Create the heap that we use to store Exprs and other temp stuff. - FreeAllTemporary(); - // Extract the command-line arguments; the ones from main() are ignored, // since they are in the OEM encoding. int argcW; @@ -681,5 +679,65 @@ void DebugPrint(const char *fmt, ...) { #endif +//----------------------------------------------------------------------------- +// Temporary arena, on Windows. +//----------------------------------------------------------------------------- + +#if defined(WIN32) + +static HANDLE TempArena = NULL; + +void *AllocTemporary(size_t size) +{ + if(!TempArena) + TempArena = HeapCreate(0, 0, 0); + void *ptr = HeapAlloc(TempArena, HEAP_ZERO_MEMORY, size); + ssassert(ptr != NULL, "out of memory"); + return ptr; +} + +void FreeAllTemporary() +{ + HeapDestroy(TempArena); + 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 guard(TempArenaMutex); + chunk->next = TempArena; + TempArena = chunk; + return (void *)(chunk + 1); +} + +void FreeAllTemporary() +{ + std::lock_guard guard(TempArenaMutex); + while(TempArena) { + ArenaChunk *chunk = TempArena; + TempArena = TempArena->next; + free(chunk); + } +} + +#endif + } } diff --git a/src/platform/platform.h b/src/platform/platform.h index adf62285..5664fa21 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -70,6 +70,10 @@ std::vector InitCli(int argc, char **argv); // Debug print function. void DebugPrint(const char *fmt, ...); +// Temporary arena functions. +void *AllocTemporary(size_t size); +void FreeAllTemporary(); + } #endif diff --git a/src/platform/utilunix.cpp b/src/platform/utilunix.cpp deleted file mode 100644 index 9a471c66..00000000 --- a/src/platform/utilunix.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//----------------------------------------------------------------------------- -// Utility functions used by the Unix port. -// -// Copyright 2008-2013 Jonathan Westhues. -// Copyright 2013 Daniel Richard G. -//----------------------------------------------------------------------------- -#include "solvespace.h" - -namespace SolveSpace { - -//----------------------------------------------------------------------------- -// A separate heap, on which we allocate expressions. Maybe a bit faster, -// since fragmentation is less of a concern, and it also makes it possible -// to be sloppy with our memory management, and just free everything at once -// at the end. -//----------------------------------------------------------------------------- - -typedef struct _AllocTempHeader AllocTempHeader; - -typedef struct _AllocTempHeader { - AllocTempHeader *prev; - AllocTempHeader *next; -} AllocTempHeader; - -static AllocTempHeader *Head = NULL; - -void *AllocTemporary(size_t n) -{ - AllocTempHeader *h = - (AllocTempHeader *)malloc(n + sizeof(AllocTempHeader)); - h->prev = NULL; - h->next = Head; - if(Head) Head->prev = h; - Head = h; - memset(&h[1], 0, n); - return (void *)&h[1]; -} - -void FreeAllTemporary() { - AllocTempHeader *h = Head; - while(h) { - AllocTempHeader *f = h; - h = h->next; - free(f); - } - Head = NULL; -} - -}; diff --git a/src/platform/utilwin.cpp b/src/platform/utilwin.cpp deleted file mode 100644 index 16bce190..00000000 --- a/src/platform/utilwin.cpp +++ /dev/null @@ -1,33 +0,0 @@ -//----------------------------------------------------------------------------- -// Utility functions that depend on Win32. -// -// Copyright 2008-2013 Jonathan Westhues. -//----------------------------------------------------------------------------- -#include "solvespace.h" - -// Include after solvespace.h to avoid identifier clashes. -#include - -namespace SolveSpace { - -//----------------------------------------------------------------------------- -// A separate heap, on which we allocate expressions. Maybe a bit faster, -// since no fragmentation issues whatsoever, and it also makes it possible -// to be sloppy with our memory management, and just free everything at once -// at the end. -//----------------------------------------------------------------------------- -static HANDLE TempHeap; - -void *AllocTemporary(size_t n) -{ - void *v = HeapAlloc(TempHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n); - ssassert(v != NULL, "Cannot allocate memory"); - return v; -} -void FreeAllTemporary() -{ - if(TempHeap) HeapDestroy(TempHeap); - TempHeap = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0); -} - -} diff --git a/src/solvespace.h b/src/solvespace.h index 165fd086..17e74b54 100644 --- a/src/solvespace.h +++ b/src/solvespace.h @@ -132,16 +132,15 @@ inline double Random(double vmax) { #include "platform/gui.h" #include "resource.h" +using Platform::AllocTemporary; +using Platform::FreeAllTemporary; + class Expr; class ExprVector; class ExprQuaternion; class RgbaColor; enum class Command : uint32_t; -// Temporary heap, defined in the platform-specific code. -void *AllocTemporary(size_t n); -void FreeAllTemporary(); - enum class Unit : uint32_t { MM = 0, INCHES,