Implement pin-based gc

This will allow for cleanup to occur mid-calculation when used throughout
This commit is contained in:
2022-11-29 21:21:16 -05:00
parent 13704fae2c
commit afaa53bb7f
3 changed files with 18 additions and 25 deletions

View File

@@ -83,7 +83,7 @@ void ucl_object_pin(struct ucl_object *obj) {
obj->flags |= UCL_OBJ_FLAG_PINNED;
}
void ucl_object_unpinned(struct ucl_object *obj) {
void ucl_object_unpin(struct ucl_object *obj) {
obj->flags &= ~UCL_OBJ_FLAG_PINNED;
}
@@ -131,52 +131,43 @@ void ucl_object_delete(struct ucl* state, struct ucl_object *obj) {
ucl_object_delete_internal(state->obj_arena, obj);
}
static void ucl_object_mark(struct ucl_object *obj) {
static void ucl_object_mark_recursive(struct ucl_object *obj) {
if (obj == NULL || obj->flags & UCL_OBJ_FLAG_REACHABLE) {
return;
}
obj->flags |= 1;
obj->flags |= UCL_OBJ_FLAG_REACHABLE;
if (obj->type == UCL_TYPE_CELL) {
ucl_object_mark(obj->cell.car);
ucl_object_mark(obj->cell.cdr);
ucl_object_mark_recursive(obj->cell.car);
ucl_object_mark_recursive(obj->cell.cdr);
}
}
static void ucl_scope_mark(struct ucl_arena * arena, void *obj) {
static void ucl_gc_mark_pinned(struct ucl_arena * arena, void *obj) {
(void) arena;
struct ucl_scope *scope = (struct ucl_scope *) obj;
struct ucl_object *object = (struct ucl_object *) obj;
ucl_object_mark(scope->list);
if (object->flags & UCL_OBJ_FLAG_PINNED) {
ucl_object_mark_recursive(object);
}
}
static void ucl_gc_unmark(struct ucl_arena * arena, void *obj) {
static void ucl_gc_unmark_all(struct ucl_arena * arena, void *obj) {
(void) arena;
struct ucl_object *object = (struct ucl_object *) obj;
object->flags &= ~UCL_OBJ_FLAG_REACHABLE;
}
static void ucl_gc_sweep(struct ucl_arena * arena, void *obj) {
(void) arena;
struct ucl_object *object = (struct ucl_object *) obj;
if (!(object->flags &UCL_OBJ_FLAG_REACHABLE)) {
ucl_object_delete_internal(arena, object);
}
}
// TODO: Implement full cleanup
/* static void ucl_gc_deleteall(struct ucl_arena * arena, void *obj) { */
/* (void) arena; */
/* struct ucl_object *object = (struct ucl_object *) obj; */
/* ucl_object_delete_internal(arena, object); */
/* } */
void ucl_gc(struct ucl* ucl) {
// TODO: Implement scope cleanup
ucl_arena_map(ucl->obj_arena, ucl_gc_unmark);
ucl_arena_map(ucl->scope_arena, ucl_scope_mark);
ucl_arena_map(ucl->obj_arena, ucl_gc_unmark_all);
ucl_arena_map(ucl->obj_arena, ucl_gc_mark_pinned);
ucl_arena_map(ucl->obj_arena, ucl_gc_sweep);
}

View File

@@ -60,12 +60,14 @@ struct ucl_scope *ucl_scope_create(struct ucl *state) {
struct ucl_scope *scope = ucl_arena_get(state->scope_arena);
scope->list = ucl_nil_create(state);
scope->parent = NULL;
ucl_object_pin(scope->list);
return scope;
}
struct ucl_scope *ucl_scope_create_child(struct ucl *state, struct ucl_scope *parent) {
struct ucl_scope *scope = ucl_scope_create(state);
scope->parent = parent;
ucl_object_pin(scope->list);
return scope;
}
@@ -78,6 +80,6 @@ struct ucl_scope *ucl_scope_get_root(struct ucl_scope *scope) {
void ucl_scope_delete(struct ucl *ucl, struct ucl_scope *scope) {
assert(ucl->scope_arena != NULL);
ucl_object_unpin(scope->list);
ucl_arena_put(ucl->scope_arena, scope);
// Garbage collection will handle the objects, they are shared
}