Use a thread-safe temporary arena on every platform.
This commit continues the work started in commitspull/616/head521473ee
ande84fd464
that parallelizes certain geometric operations. This commit cleans up the temporary arena implementations and makes them thread-safe. Also, in commit521473ee
, a call to FreeAllTemporary() was added during initialization to create the heap on Windows. This is now not necessary as the heap is created transparently on the first call to AllocTemporary().
parent
060a3280f7
commit
c89a2e4f62
|
@ -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})
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#else
|
||||
# include <unistd.h>
|
||||
# include <sys/stat.h>
|
||||
# include <mutex>
|
||||
#endif
|
||||
|
||||
namespace SolveSpace {
|
||||
|
@ -605,9 +606,6 @@ std::vector<std::string> 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<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
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,6 +70,10 @@ std::vector<std::string> InitCli(int argc, char **argv);
|
|||
// Debug print function.
|
||||
void DebugPrint(const char *fmt, ...);
|
||||
|
||||
// Temporary arena functions.
|
||||
void *AllocTemporary(size_t size);
|
||||
void FreeAllTemporary();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Utility functions used by the Unix port.
|
||||
//
|
||||
// Copyright 2008-2013 Jonathan Westhues.
|
||||
// Copyright 2013 Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||
//-----------------------------------------------------------------------------
|
||||
#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;
|
||||
}
|
||||
|
||||
};
|
|
@ -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 <windows.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue