diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ac7456..952ac3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ project(libabacus) add_compile_options(-pedantic -Wall) -add_library(abacus STATIC src/lexer.c src/util.c src/table.c src/parser.c src/libabacus.c src/tree.c src/debug.c src/parsetype.c src/reserved.c src/trie.c src/refcount.c src/ref_vec.c src/ref_trie.c src/basetype.c src/value.c src/custom.c src/interpreter.c src/function_list.c src/free_functions.c) +add_library(abacus STATIC src/lexer.c src/util.c src/table.c src/parser.c src/libabacus.c src/tree.c src/debug.c src/parsetype.c src/reserved.c src/trie.c src/refcount.c src/ref_vec.c src/ref_trie.c src/basetype.c src/value.c src/custom.c src/interpreter.c src/function_list.c src/free_functions.c src/gc.c) add_executable(libabacus src/main.c) add_executable(interactive src/interactive.c) add_subdirectory(external/liblex) @@ -20,4 +20,4 @@ target_include_directories(libabacus PUBLIC include) target_link_libraries(abacus lex) target_link_libraries(libabacus abacus) -target_link_libraries(interactive abacus) +target_link_libraries(interactive abacus m) diff --git a/include/gc.h b/include/gc.h new file mode 100644 index 0000000..835d573 --- /dev/null +++ b/include/gc.h @@ -0,0 +1,33 @@ +#ifndef LIBABACUS_GC_H +#define LIBABACUS_GC_H + +struct libab_ref_s; +struct libab_ref_count_s; + +/** + * Struct used to create an interface + * for a set of objects to be collected. + */ +struct libab_gc_list_s { + /** + * The head of the linked list. + */ + struct libab_ref_count_s* head; + /** + * The tail of the linked list. + */ + struct libab_ref_count_s* tail; +}; + +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*); + +void libab_gc_list_init(libab_gc_list* list); +void libab_gc_visit(struct libab_ref_s*, libab_visitor_function_ptr visitor, void*); +void libab_gc_add(struct libab_ref_s* ref, + libab_visit_function_ptr visit_children, + libab_gc_list* list); +void libab_gc_run(libab_gc_list* list); + +#endif diff --git a/include/refcount.h b/include/refcount.h index 5f8b7a3..0c24ee2 100644 --- a/include/refcount.h +++ b/include/refcount.h @@ -2,12 +2,7 @@ #define LIBABACUS_REFCOUNT_H #include "result.h" - -struct libab_ref_s; -struct libab_ref_count_s; - -typedef void (*libab_visitor_function_ptr)(struct libab_ref_count_s* , void*); -typedef void (*libab_visit_function_ptr)(void*, libab_visitor_function_ptr, void*); +#include "gc.h" /** * A struct for holding @@ -57,21 +52,6 @@ struct libab_ref_count_s { libab_visit_function_ptr visit_children; }; -/** - * Struct used to create an interface - * for a set of objects to be collected. - */ -struct libab_ref_gc_list_s { - /** - * The head of the linked list. - */ - struct libab_ref_count_s* head; - /** - * The tail of the linked list. - */ - struct libab_ref_count_s* tail; -}; - /** * A reference to a value. */ @@ -93,7 +73,6 @@ struct libab_ref_s { typedef struct libab_ref_s libab_ref; typedef struct libab_ref_count_s libab_ref_count; -typedef struct libab_ref_gc_list_s libab_ref_gc_list; /** * Creates a new referene, using the given data and free function. @@ -111,11 +90,6 @@ libab_result libab_ref_new(libab_ref* ref, void* data, * @param ref the reference to initialize with null. */ void libab_ref_null(libab_ref* ref); -void libab_ref_gc_visit(libab_ref*, libab_visitor_function_ptr visitor, void*); -void libab_ref_gc_add(libab_ref* ref, - libab_visit_function_ptr visit_children, - libab_ref_gc_list* list); -void libab_ref_gc_run(libab_ref_gc_list* list); /** * Turns the given reference into a weak reference, * making it not keep the data allocated. diff --git a/src/gc.c b/src/gc.c new file mode 100644 index 0000000..f2c171d --- /dev/null +++ b/src/gc.c @@ -0,0 +1,77 @@ +#include "gc.h" +#include "refcount.h" +#include + +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) { + 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_list_append(libab_gc_list* list, + libab_ref_count* node) { + if(node->next) node->next->prev = node->prev; + if(node->prev) node->prev->next = node->next; + + node->prev = list->tail; + node->next = NULL; + if(list->head) { + list->tail->next = node; + } else { + list->head = node; + } + list->tail = node; +} +void libab_gc_add(libab_ref* ref, + libab_visit_function_ptr visit_children, + libab_gc_list* list) { + ref->count->visit_children = visit_children; + _libab_gc_list_append(list, ref->count); +} + +void _gc_decrement(libab_ref_count* count, void* data) { + count->gc--; +} +void _gc_save(libab_ref_count* count, void* data) { + libab_gc_list* list = data; + if(count->gc != -1) { + count->gc = -1; + _libab_gc_list_append(list, count); + _gc_count_visit(count, _gc_save, data); + } +} + +void libab_gc_run(libab_gc_list* list) { + libab_gc_list safe; + libab_ref_count* head; + size_t count = 0; + + head = list->head; + while(head) { + head->gc = head->weak; + } + + head = list->head; + while(head) { + _gc_count_visit(head, _gc_decrement, NULL); + } + + head = list->head; + while(head) { + _gc_count_visit(head, _gc_save, &safe); + } + + head = list->head; + while(head) { + count++; + } + printf("Can free %d\n", count); + + list->head = safe.head; + list->tail = safe.tail; +} diff --git a/src/refcount.c b/src/refcount.c index 5066b07..97226c1 100644 --- a/src/refcount.c +++ b/src/refcount.c @@ -21,76 +21,6 @@ libab_result libab_ref_new(libab_ref* ref, void* data, void libab_ref_null(libab_ref* ref) { ref->null = 1; } -void _ref_gc_count_visit(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_ref_gc_visit(libab_ref* ref, libab_visitor_function_ptr func, void* data) { - _ref_gc_count_visit(ref->count, func, data); -} - -void _libab_ref_gc_list_append(libab_ref_gc_list* list, - libab_ref_count* node) { - if(node->next) node->next->prev = node->prev; - if(node->prev) node->prev->next = node->next; - - node->prev = list->tail; - node->next = NULL; - if(list->head) { - list->tail->next = node; - } else { - list->head = node; - } - list->tail = node; -} -void libab_ref_gc_add(libab_ref* ref, - libab_visit_function_ptr visit_children, - libab_ref_gc_list* list) { - ref->count->visit_children = visit_children; - _libab_ref_gc_list_append(list, ref->count); -} - -void _ref_gc_decrement(libab_ref_count* count, void* data) { - count->gc--; -} -void _ref_gc_save(libab_ref_count* count, void* data) { - libab_ref_gc_list* list = data; - if(count->gc != -1) { - count->gc = -1; - _libab_ref_gc_list_append(list, count); - _ref_gc_count_visit(count, _ref_gc_save, data); - } -} - -void libab_ref_gc_run(libab_ref_gc_list* list) { - libab_ref_gc_list safe; - libab_ref_count* head; - size_t count = 0; - - head = list->head; - while(head) { - head->gc = head->weak; - } - - head = list->head; - while(head) { - _ref_gc_count_visit(head, _ref_gc_decrement, NULL); - } - - head = list->head; - while(head) { - _ref_gc_count_visit(head, _ref_gc_save, &safe); - } - - head = list->head; - while(head) { - count++; - } - printf("Can free %d\n", count); - - list->head = safe.head; - list->tail = safe.tail; -} - void _libab_ref_changed(libab_ref* ref) { if (ref->count->strong == 0) { ref->count->strong--;