diff --git a/include/gc.h b/include/gc.h index 835d573..b951b44 100644 --- a/include/gc.h +++ b/include/gc.h @@ -23,11 +23,32 @@ typedef struct libab_gc_list_s libab_gc_list; typedef void (*libab_visitor_function_ptr)(struct libab_ref_count_s* , void*); typedef void (*libab_visit_function_ptr)(void*, libab_visitor_function_ptr, void*); +/** + * Initializes a garbage collection tracking list. + * @param list the list to initialize. + */ void libab_gc_list_init(libab_gc_list* list); -void libab_gc_visit(struct libab_ref_s*, libab_visitor_function_ptr visitor, void*); +/** + * Visits the children of the current node, applying the given function to them. + * @param ref the reference whose children to visit. + * @param visitor the function to call for each child. + * @param data the data to pass to the visitor. + */ +void libab_gc_visit_chilren(struct libab_ref_s* ref, libab_visitor_function_ptr visitor, void* data); +/** + * Adds the given reference to the given garbage collection list, + * and specifies a function used to reach its children. + * @param ref the reference whose children to visit. + * @param visit_children the function used to reach the chilren of this reference. + * @param list the list to which to add the reference. + */ void libab_gc_add(struct libab_ref_s* ref, libab_visit_function_ptr visit_children, libab_gc_list* list); +/** + * Performs garbage collection on a given list of container objects/ + * @param list the list to run collection on. + */ void libab_gc_run(libab_gc_list* list); #endif diff --git a/src/gc.c b/src/gc.c index f2c171d..98ce12e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -6,11 +6,11 @@ void libab_gc_list_init(libab_gc_list* list) { list->head = list->tail = NULL; } -void _gc_count_visit(libab_ref_count* ref, libab_visitor_function_ptr func, void* data) { +void _gc_count_visit_children(libab_ref_count* ref, libab_visitor_function_ptr func, void* data) { if(ref->strong && ref->visit_children) ref->visit_children(ref->data, func, data); } -void libab_gc_visit(libab_ref* ref, libab_visitor_function_ptr func, void* data) { - _gc_count_visit(ref->count, func, data); +void libab_gc_visit_children(libab_ref* ref, libab_visitor_function_ptr func, void* data) { + _gc_count_visit_children(ref->count, func, data); } void _libab_gc_list_append(libab_gc_list* list, @@ -35,14 +35,14 @@ void libab_gc_add(libab_ref* ref, } void _gc_decrement(libab_ref_count* count, void* data) { - count->gc--; + if(count->visit_children) count->gc--; } void _gc_save(libab_ref_count* count, void* data) { libab_gc_list* list = data; - if(count->gc != -1) { + if(count->visit_children && count->gc != -1) { count->gc = -1; _libab_gc_list_append(list, count); - _gc_count_visit(count, _gc_save, data); + _gc_count_visit_children(count, _gc_save, data); } } @@ -58,12 +58,12 @@ void libab_gc_run(libab_gc_list* list) { head = list->head; while(head) { - _gc_count_visit(head, _gc_decrement, NULL); + _gc_count_visit_children(head, _gc_decrement, NULL); } head = list->head; while(head) { - _gc_count_visit(head, _gc_save, &safe); + _gc_count_visit_children(head, _gc_save, &safe); } head = list->head; diff --git a/src/refcount.c b/src/refcount.c index b02003b..0efb90c 100644 --- a/src/refcount.c +++ b/src/refcount.c @@ -11,6 +11,7 @@ libab_result libab_ref_new(libab_ref* ref, void* data, ref->count->data = data; ref->count->strong = ref->count->weak = 1; ref->count->free_func = free_func; + ref->count->visit_children = NULL; ref->count->prev = NULL; ref->count->next = NULL; } else {