[mem] change scratch arena API to allow using independant scratch for temporary computations and results

This commit is contained in:
Martin Fouilleul 2023-05-24 20:17:03 +02:00
parent 02bfe587c8
commit ba125ae860
8 changed files with 98 additions and 48 deletions

View File

@ -480,14 +480,14 @@ void mp_install_keyboard_layout_listener()
event.type = MP_EVENT_PATHDROP; event.type = MP_EVENT_PATHDROP;
mem_arena* scratch = mem_scratch(); mem_arena* scratch = mem_scratch();
mem_arena_marker mark = mem_arena_mark(scratch); mem_arena_scope scope = mem_arena_scope_begin(scratch);
str8 path = str8_push_cstring(scratch, [filename UTF8String]); str8 path = str8_push_cstring(scratch, [filename UTF8String]);
str8_list_push(scratch, &event.paths, path); str8_list_push(scratch, &event.paths, path);
mp_queue_event(&event); mp_queue_event(&event);
mem_arena_clear_to(scratch, mark); mem_arena_scope_end(scope);
return(YES); return(YES);
} }
@ -501,14 +501,14 @@ void mp_install_keyboard_layout_listener()
event.type = MP_EVENT_PATHDROP; event.type = MP_EVENT_PATHDROP;
mem_arena* scratch = mem_scratch(); mem_arena* scratch = mem_scratch();
mem_arena_marker mark = mem_arena_mark(scratch); mem_arena_scope scope = mem_arena_scope_begin(scratch);
str8 path = str8_push_cstring(scratch, [nsPath UTF8String]); str8 path = str8_push_cstring(scratch, [nsPath UTF8String]);
str8_list_push(scratch, &event.paths, path); str8_list_push(scratch, &event.paths, path);
mp_queue_event(&event); mp_queue_event(&event);
mem_arena_clear_to(scratch, mark); mem_arena_scope_end(scope);
} }
//TODO: drag and drop paths //TODO: drag and drop paths

View File

@ -58,7 +58,7 @@ void platform_log_push(log_output* output,
va_list ap) va_list ap)
{ {
mem_arena* scratch = mem_scratch(); mem_arena* scratch = mem_scratch();
mem_arena_marker marker = mem_arena_mark(scratch); mem_arena_scope tmp = mem_arena_scope_begin(scratch);
orca_log_context ctx = {.arena = scratch, orca_log_context ctx = {.arena = scratch,
.list = {0}}; .list = {0}};
@ -70,5 +70,5 @@ void platform_log_push(log_output* output,
orca_log(level, str8_ip(function), str8_ip(file), line, str8_ip(string)); orca_log(level, str8_ip(function), str8_ip(file), line, str8_ip(string));
mem_arena_clear_to(scratch, marker); mem_arena_scope_end(tmp);
} }

View File

@ -55,10 +55,3 @@ str8 path_find_canonical(mem_arena* arena, str8 path)
return(result); return(result);
} }
/*TODO
str8 path_find_restricted(mem_arena* arena, str8 root, str8 relPath)
{
}
*/

View File

@ -56,7 +56,7 @@ str8 path_join(mem_arena* arena, str8_list elements)
return(res); return(res);
} }
str8 path_append_relative(mem_arena* arena, str8 parent, str8 relPath) str8 path_append(mem_arena* arena, str8 parent, str8 relPath)
{ {
//TODO: use secondary scratch arena //TODO: use secondary scratch arena

View File

@ -15,11 +15,10 @@ MP_API str8 path_slice_filename(str8 path);
MP_API str8_list path_split(mem_arena* arena, str8 path); MP_API str8_list path_split(mem_arena* arena, str8 path);
MP_API str8 path_join(mem_arena* arena, str8_list elements); MP_API str8 path_join(mem_arena* arena, str8_list elements);
MP_API str8 path_append_relative(mem_arena* arena, str8 parent, str8 relPath); MP_API str8 path_append(mem_arena* arena, str8 parent, str8 relPath);
MP_API str8 path_find_executable(mem_arena* arena); MP_API str8 path_find_executable(mem_arena* arena);
MP_API str8 path_find_resource(mem_arena* arena, str8 relPath); MP_API str8 path_find_resource(mem_arena* arena, str8 relPath);
MP_API str8 path_find_canonical(mem_arena* arena, str8 path); MP_API str8 path_find_canonical(mem_arena* arena, str8 path);
MP_API str8 path_find_restricted(mem_arena* arena, str8 root, str8 relPath);
#endif //__PLATFORM_PATH_H_ #endif //__PLATFORM_PATH_H_

View File

@ -115,19 +115,18 @@ void mem_arena_clear(mem_arena* arena)
arena->currentChunk = list_first_entry(&arena->chunks, mem_arena_chunk, listElt); arena->currentChunk = list_first_entry(&arena->chunks, mem_arena_chunk, listElt);
} }
mem_arena_marker mem_arena_mark(mem_arena* arena) mem_arena_scope mem_arena_scope_begin(mem_arena* arena)
{ {
mem_arena_marker marker = {.arena = arena, mem_arena_scope scope = {.arena = arena,
.chunk = arena->currentChunk, .chunk = arena->currentChunk,
.offset = arena->currentChunk->offset}; .offset = arena->currentChunk->offset};
return(marker); return(scope);
} }
void mem_arena_clear_to(mem_arena* arena, mem_arena_marker marker) void mem_arena_scope_end(mem_arena_scope scope)
{ {
DEBUG_ASSERT(arena == marker.arena); scope.arena->currentChunk = scope.chunk;
arena->currentChunk = marker.chunk; scope.arena->currentChunk->offset = scope.offset;
arena->currentChunk->offset = marker.offset;
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
@ -178,18 +177,65 @@ void mem_pool_clear(mem_pool* pool)
//NOTE(martin): per-thread scratch arena //NOTE(martin): per-thread scratch arena
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
mp_thread_local mem_arena __scratchArena = {0}; enum
{
MEM_SCRATCH_POOL_SIZE = 8,
MEM_SCRATCH_DEFAULT_SIZE = 4096,
};
mp_thread_local mem_arena __scratchPool[MEM_SCRATCH_POOL_SIZE] = {0};
static mem_arena* mem_scratch_at_index(int index)
{
mem_arena* scratch = 0;
if(index >= 0 && index < MEM_SCRATCH_POOL_SIZE)
{
if(__scratchPool[index].base == 0)
{
mem_arena_options options = {.reserve = MEM_SCRATCH_DEFAULT_SIZE};
mem_arena_init_with_options(&__scratchPool[index], &options);
}
scratch = &__scratchPool[index];
}
return(scratch);
}
mem_arena* mem_scratch() mem_arena* mem_scratch()
{ {
if(__scratchArena.base == 0) return(mem_scratch_at_index(0));
{
mem_arena_init(&__scratchArena);
}
return(&__scratchArena);
} }
void mem_scratch_clear() MP_API mem_arena* mem_scratch_next(mem_arena* used)
{ {
mem_arena_clear(mem_scratch()); mem_arena* res = 0;
if( (used >= __scratchPool)
&&(used - __scratchPool < MEM_SCRATCH_POOL_SIZE))
{
u64 index = used - __scratchPool;
if(index + 1 < MEM_SCRATCH_POOL_SIZE)
{
res = mem_scratch_at_index(index+1);
}
}
else
{
res = mem_scratch_at_index(0);
}
return(res);
}
MP_API mem_arena_scope mem_scratch_begin()
{
mem_arena* scratch = mem_scratch();
mem_arena_scope scope = mem_arena_scope_begin(scratch);
return(scope);
}
MP_API mem_arena_scope mem_scratch_begin_next(mem_arena* used)
{
mem_arena* scratch = mem_scratch_next(used);
mem_arena_scope scope = mem_arena_scope_begin(scratch);
return(scope);
} }

View File

@ -38,12 +38,12 @@ typedef struct mem_arena
} mem_arena; } mem_arena;
typedef struct mem_arena_marker typedef struct mem_arena_scope
{ {
mem_arena* arena; mem_arena* arena;
mem_arena_chunk* chunk; mem_arena_chunk* chunk;
u64 offset; u64 offset;
} mem_arena_marker; } mem_arena_scope;
typedef struct mem_arena_options typedef struct mem_arena_options
{ {
@ -57,8 +57,9 @@ MP_API void mem_arena_release(mem_arena* arena);
MP_API void* mem_arena_alloc(mem_arena* arena, u64 size); MP_API void* mem_arena_alloc(mem_arena* arena, u64 size);
MP_API void mem_arena_clear(mem_arena* arena); MP_API void mem_arena_clear(mem_arena* arena);
MP_API mem_arena_marker mem_arena_mark(mem_arena* arena);
MP_API void mem_arena_clear_to(mem_arena* arena, mem_arena_marker marker); MP_API mem_arena_scope mem_arena_scope_begin(mem_arena* arena);
MP_API void mem_arena_scope_end(mem_arena_scope scope);
#define mem_arena_alloc_type(arena, type) ((type*)mem_arena_alloc(arena, sizeof(type))) #define mem_arena_alloc_type(arena, type) ((type*)mem_arena_alloc(arena, sizeof(type)))
#define mem_arena_alloc_array(arena, type, count) ((type*)mem_arena_alloc(arena, sizeof(type)*(count))) #define mem_arena_alloc_array(arena, type, count) ((type*)mem_arena_alloc(arena, sizeof(type)*(count)))
@ -66,6 +67,10 @@ MP_API void mem_arena_clear_to(mem_arena* arena, mem_arena_marker marker);
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
//NOTE(martin): memory pool //NOTE(martin): memory pool
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
//TODO: we could probably remove pool. Most of the time we construct pool on top of
// arenas "manually" with different free lists per object types...
typedef struct mem_pool typedef struct mem_pool
{ {
mem_arena arena; mem_arena arena;
@ -92,8 +97,15 @@ MP_API void mem_pool_clear(mem_pool* pool);
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
//NOTE(martin): per-thread implicit scratch arena //NOTE(martin): per-thread implicit scratch arena
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------
MP_API void mem_scratch_clear();
MP_API mem_arena* mem_scratch(); MP_API mem_arena* mem_scratch();
MP_API mem_arena* mem_scratch_next(mem_arena* used);
MP_API mem_arena_scope mem_scratch_begin();
MP_API mem_arena_scope mem_scratch_begin_next(mem_arena* used);
#define mem_scratch_end(scope) mem_arena_scope_end(scope)
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View File

@ -1118,7 +1118,7 @@ MP_API str8 mp_open_dialog(mem_arena* arena,
if(filterCount && filters) if(filterCount && filters)
{ {
mem_arena_marker mark = mem_arena_mark(arena); mem_arena_scope tmp = mem_arena_scope_begin(arena);
COMDLG_FILTERSPEC* filterSpecs = mem_arena_alloc_array(arena, COMDLG_FILTERSPEC, filterCount); COMDLG_FILTERSPEC* filterSpecs = mem_arena_alloc_array(arena, COMDLG_FILTERSPEC, filterCount);
for(int i=0; i<filterCount; i++) for(int i=0; i<filterCount; i++)
{ {
@ -1137,12 +1137,12 @@ MP_API str8 mp_open_dialog(mem_arena* arena,
hr = dialog->lpVtbl->SetFileTypes(dialog, filterCount, filterSpecs); hr = dialog->lpVtbl->SetFileTypes(dialog, filterCount, filterSpecs);
mem_arena_clear_to(arena, mark); mem_arena_scope_end(tmp);
} }
if(defaultPath) if(defaultPath)
{ {
mem_arena_marker mark = mem_arena_mark(arena); mem_arena_scope tmp = mem_arena_scope_begin(arena);
int pathWideSize = MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, NULL, 0); int pathWideSize = MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, NULL, 0);
LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, pathWideSize); LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, pathWideSize);
MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, pathWide, pathWideSize); MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, pathWide, pathWideSize);
@ -1154,7 +1154,7 @@ MP_API str8 mp_open_dialog(mem_arena* arena,
hr = dialog->lpVtbl->SetFolder(dialog, item); hr = dialog->lpVtbl->SetFolder(dialog, item);
item->lpVtbl->Release(item); item->lpVtbl->Release(item);
} }
mem_arena_clear_to(arena, mark); mem_arena_scope_end(tmp);
} }
hr = dialog->lpVtbl->Show(dialog, NULL); hr = dialog->lpVtbl->Show(dialog, NULL);
@ -1203,7 +1203,7 @@ MP_API str8 mp_save_dialog(mem_arena* arena,
{ {
if(filterCount && filters) if(filterCount && filters)
{ {
mem_arena_marker mark = mem_arena_mark(arena); mem_arena_scope tmp = mem_arena_scope_begin(arena);
COMDLG_FILTERSPEC* filterSpecs = mem_arena_alloc_array(arena, COMDLG_FILTERSPEC, filterCount); COMDLG_FILTERSPEC* filterSpecs = mem_arena_alloc_array(arena, COMDLG_FILTERSPEC, filterCount);
for(int i=0; i<filterCount; i++) for(int i=0; i<filterCount; i++)
{ {
@ -1222,12 +1222,12 @@ MP_API str8 mp_save_dialog(mem_arena* arena,
hr = dialog->lpVtbl->SetFileTypes(dialog, filterCount, filterSpecs); hr = dialog->lpVtbl->SetFileTypes(dialog, filterCount, filterSpecs);
mem_arena_clear_to(arena, mark); mem_arena_scope_end(tmp);
} }
if(defaultPath) if(defaultPath)
{ {
mem_arena_marker mark = mem_arena_mark(arena); mem_arena_scope tmp = mem_arena_scope_begin(arena);
int pathWideSize = MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, NULL, 0); int pathWideSize = MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, NULL, 0);
LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, pathWideSize); LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, pathWideSize);
MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, pathWide, pathWideSize); MultiByteToWideChar(CP_UTF8, 0, defaultPath, -1, pathWide, pathWideSize);
@ -1239,7 +1239,7 @@ MP_API str8 mp_save_dialog(mem_arena* arena,
hr = dialog->lpVtbl->SetFolder(dialog, item); hr = dialog->lpVtbl->SetFolder(dialog, item);
item->lpVtbl->Release(item); item->lpVtbl->Release(item);
} }
mem_arena_clear_to(arena, mark); mem_arena_scope_end(tmp);
} }
hr = dialog->lpVtbl->Show(dialog, NULL); hr = dialog->lpVtbl->Show(dialog, NULL);
@ -1280,7 +1280,7 @@ MP_API int mp_alert_popup(const char* title,
const char** options) const char** options)
{ {
mem_arena* scratch = mem_scratch(); mem_arena* scratch = mem_scratch();
mem_arena_marker marker = mem_arena_mark(scratch); mem_arena_scope tmp = mem_arena_scope_begin(scratch);
TASKDIALOG_BUTTON* buttons = mem_arena_alloc_array(scratch, TASKDIALOG_BUTTON, count); TASKDIALOG_BUTTON* buttons = mem_arena_alloc_array(scratch, TASKDIALOG_BUTTON, count);
for(int i=0; i<count; i++) for(int i=0; i<count; i++)
@ -1332,6 +1332,6 @@ MP_API int mp_alert_popup(const char* title,
} }
} }
mem_arena_clear_to(scratch, marker); mem_arena_scope_end(tmp);
return(button); return(button);
} }