[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;
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_list_push(scratch, &event.paths, path);
mp_queue_event(&event);
mem_arena_clear_to(scratch, mark);
mem_arena_scope_end(scope);
return(YES);
}
@ -501,14 +501,14 @@ void mp_install_keyboard_layout_listener()
event.type = MP_EVENT_PATHDROP;
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_list_push(scratch, &event.paths, path);
mp_queue_event(&event);
mem_arena_clear_to(scratch, mark);
mem_arena_scope_end(scope);
}
//TODO: drag and drop paths

View File

@ -58,7 +58,7 @@ void platform_log_push(log_output* output,
va_list ap)
{
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,
.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));
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);
}
/*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);
}
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

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 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_resource(mem_arena* arena, str8 relPath);
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_

View File

@ -115,19 +115,18 @@ void mem_arena_clear(mem_arena* arena)
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,
.chunk = arena->currentChunk,
.offset = arena->currentChunk->offset};
return(marker);
mem_arena_scope scope = {.arena = arena,
.chunk = arena->currentChunk,
.offset = arena->currentChunk->offset};
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);
arena->currentChunk = marker.chunk;
arena->currentChunk->offset = marker.offset;
scope.arena->currentChunk = scope.chunk;
scope.arena->currentChunk->offset = scope.offset;
}
//--------------------------------------------------------------------------------
@ -178,18 +177,65 @@ void mem_pool_clear(mem_pool* pool)
//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()
{
if(__scratchArena.base == 0)
{
mem_arena_init(&__scratchArena);
}
return(&__scratchArena);
return(mem_scratch_at_index(0));
}
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;
typedef struct mem_arena_marker
typedef struct mem_arena_scope
{
mem_arena* arena;
mem_arena_chunk* chunk;
u64 offset;
} mem_arena_marker;
} mem_arena_scope;
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_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_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
//--------------------------------------------------------------------------------
//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
{
mem_arena arena;
@ -92,8 +97,15 @@ MP_API void mem_pool_clear(mem_pool* pool);
//--------------------------------------------------------------------------------
//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_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
} // extern "C"

View File

@ -1118,7 +1118,7 @@ MP_API str8 mp_open_dialog(mem_arena* arena,
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);
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);
mem_arena_clear_to(arena, mark);
mem_arena_scope_end(tmp);
}
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);
LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, 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);
item->lpVtbl->Release(item);
}
mem_arena_clear_to(arena, mark);
mem_arena_scope_end(tmp);
}
hr = dialog->lpVtbl->Show(dialog, NULL);
@ -1203,7 +1203,7 @@ MP_API str8 mp_save_dialog(mem_arena* arena,
{
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);
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);
mem_arena_clear_to(arena, mark);
mem_arena_scope_end(tmp);
}
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);
LPWSTR pathWide = mem_arena_alloc_array(arena, wchar_t, 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);
item->lpVtbl->Release(item);
}
mem_arena_clear_to(arena, mark);
mem_arena_scope_end(tmp);
}
hr = dialog->lpVtbl->Show(dialog, NULL);
@ -1280,7 +1280,7 @@ MP_API int mp_alert_popup(const char* title,
const char** options)
{
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);
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);
}