Move GC code to separate source file.
This commit is contained in:
parent
ec2421e5d7
commit
9eae28928a
|
@ -8,7 +8,7 @@ project(libabacus)
|
||||||
|
|
||||||
add_compile_options(-pedantic -Wall)
|
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(libabacus src/main.c)
|
||||||
add_executable(interactive src/interactive.c)
|
add_executable(interactive src/interactive.c)
|
||||||
add_subdirectory(external/liblex)
|
add_subdirectory(external/liblex)
|
||||||
|
@ -20,4 +20,4 @@ target_include_directories(libabacus PUBLIC include)
|
||||||
|
|
||||||
target_link_libraries(abacus lex)
|
target_link_libraries(abacus lex)
|
||||||
target_link_libraries(libabacus abacus)
|
target_link_libraries(libabacus abacus)
|
||||||
target_link_libraries(interactive abacus)
|
target_link_libraries(interactive abacus m)
|
||||||
|
|
33
include/gc.h
Normal file
33
include/gc.h
Normal file
|
@ -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
|
|
@ -2,12 +2,7 @@
|
||||||
#define LIBABACUS_REFCOUNT_H
|
#define LIBABACUS_REFCOUNT_H
|
||||||
|
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
|
#include "gc.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*);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A struct for holding
|
* A struct for holding
|
||||||
|
@ -57,21 +52,6 @@ struct libab_ref_count_s {
|
||||||
libab_visit_function_ptr visit_children;
|
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.
|
* A reference to a value.
|
||||||
*/
|
*/
|
||||||
|
@ -93,7 +73,6 @@ struct libab_ref_s {
|
||||||
|
|
||||||
typedef struct libab_ref_s libab_ref;
|
typedef struct libab_ref_s libab_ref;
|
||||||
typedef struct libab_ref_count_s libab_ref_count;
|
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.
|
* 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.
|
* @param ref the reference to initialize with null.
|
||||||
*/
|
*/
|
||||||
void libab_ref_null(libab_ref* ref);
|
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,
|
* Turns the given reference into a weak reference,
|
||||||
* making it not keep the data allocated.
|
* making it not keep the data allocated.
|
||||||
|
|
77
src/gc.c
Normal file
77
src/gc.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include "gc.h"
|
||||||
|
#include "refcount.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -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 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) {
|
void _libab_ref_changed(libab_ref* ref) {
|
||||||
if (ref->count->strong == 0) {
|
if (ref->count->strong == 0) {
|
||||||
ref->count->strong--;
|
ref->count->strong--;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user