From c308aa8ecce00fb0dd2606cbf482084876dc4910 Mon Sep 17 00:00:00 2001 From: Maciej Samborski Date: Mon, 25 Nov 2024 17:38:47 +0100 Subject: [PATCH] Add cgc support --- cgc.h | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ da.h | 34 +++++++++++++++- example.c | 19 ++++----- 3 files changed, 157 insertions(+), 10 deletions(-) create mode 100644 cgc.h diff --git a/cgc.h b/cgc.h new file mode 100644 index 0000000..faba34d --- /dev/null +++ b/cgc.h @@ -0,0 +1,114 @@ +#ifndef CGC_H_ +#define CGC_H_ + +#include +#include + +#define GC_DEFAULT_CAP 16 +#include + +typedef struct { + void * ptr; + size_t id; +} GCItem; + +typedef struct { + GCItem * items; + size_t size; + size_t capacity; +} GC; + +typedef size_t GCIndex; + +GC gcInit(void); +void gcDeinit(GC gc); +void gcGrowBuffer(GC * gc); +GCIndex gcAddItem(GC * gc, void * ptr); +void * gcAlloc(GC * gc, size_t elemNo, size_t elemSize); +void gcUpdateItem(GC * gc, GCIndex id, void * ptr); +void * gcGetPtrAt(GC gc, GCIndex id); + +#ifdef CGC_IMPLEMENTATION + +GC gcInit() +{ + void * items = calloc(GC_DEFAULT_CAP, sizeof(GCItem)); + if (items == NULL) { + fprintf(stderr, "ERROR: Failed to allocate GC!\n"); + exit(1); + } + + return (GC) { + .items = items, + .size = 0, + .capacity = GC_DEFAULT_CAP, + }; +} + +void gcDeinit(GC gc) +{ + for (size_t i = 0; i < gc.size; ++i) + free(gc.items[i].ptr); + + free(gc.items); +} + +void gcGrowBuffer(GC * gc) +{ + if (gc->items == NULL) + { + fprintf(stderr, "ERROR: GC is not initialized!\n"); + exit(1); + } + + size_t newCap = gc->capacity * 2; + + void * items = calloc(newCap, sizeof(GCItem)); + if (items == NULL) { + fprintf(stderr, "ERROR: Failed to allocate GC!\n"); + exit(1); + } + memcpy(items, gc->items, gc->capacity * sizeof(GCItem)); + free(gc->items); + gc->items = items; + gc->capacity = newCap; +} + +GCIndex gcAddItem(GC * gc, void * ptr) +{ + if (gc->size >= gc->capacity) + gcGrowBuffer(gc); + + gc->size += 1; + gc->items[gc->size - 1] = (GCItem) { + .id = gc->size - 1, + .ptr = ptr, + }; + + return gc->size - 1; +} + +void * gcAlloc(GC * gc, size_t elemNo, size_t elemSize) +{ + void * ptr = calloc(elemNo, elemSize); + if (ptr == NULL) return NULL; + + gcAddItem(gc, ptr); + + return ptr; +} + +void gcUpdateItem(GC * gc, GCIndex id, void * ptr) +{ + free(gc->items[id].ptr); + gc->items[id].ptr = ptr; +} + +void * gcGetPtrAt(GC gc, GCIndex id) +{ + return gc.items[id].ptr; +} + +#endif // CGC_IMPLEMENTATION + +#endif // CGC_H_ diff --git a/da.h b/da.h index 37a1b9a..f9e9a56 100644 --- a/da.h +++ b/da.h @@ -10,6 +10,9 @@ #define EHAN_IMPLEMENTATION #include "ehan.h" +#define CGC_IMPLEMENTATION +#include "cgc.h" + enum daFields { SIZE = 0, CAPACITY = 1, @@ -73,11 +76,29 @@ void daBzero(dynarr da); #ifdef DA_IMPLEMENTATION +#ifdef DA_GC +GC daGarbageCollector = {0}; + +void daInitGC() +{ + daGarbageCollector = gcInit(); +} + +void daDeinitGC() +{ + gcDeinit(daGarbageCollector); +} +#endif + dynarr _daCreate(size_t cap, size_t type, size_t size) { size_t realCap = (((int)(cap / 8)) + 1 ) * 8; - +#ifdef DA_GC + size_t * da = (size_t *) gcAlloc(&daGarbageCollector, 1, type * realCap + DATA * sizeof(size_t)); +#else size_t * da = (size_t *) calloc(1, type * realCap + DATA * sizeof(size_t)); +#endif + if (da == NULL) return NULL; @@ -118,7 +139,18 @@ dynarr daResize(dynarr da) return NULL; memcpy(newArr, da, daSize(da) * daType(da)); + + // TODO: Make use of the GCIndex returned from gcAlloc ! + for (size_t i = 0; i < daGarbageCollector.size; ++i) + { + if (daGarbageCollector.items[i].ptr == da) + gcUpdateItem(&daGarbageCollector, i, newArr); + } + +#ifndef DA_GC daFree(da); +#endif + return newArr; } diff --git a/example.c b/example.c index ce2f945..10ac9da 100644 --- a/example.c +++ b/example.c @@ -1,6 +1,7 @@ #include #include +#define DA_GC #define DA_IMPLEMENTATION #include "da.h" @@ -9,12 +10,14 @@ int main(void) { + daInitGC(); + dynarr(int) da = daCreate(int, 8); dynarr(char *) da2 = daCreate(char *, 8); dynarr(float) da3 = daCreate(float, 1); - if (!da) goto cleanup; - if (!da2) goto cleanup; - if (!da3) goto cleanup; + if (!da) goto exit; + if (!da2) goto exit; + if (!da3) goto exit; printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da)); printf("errno: %d\n", errno); @@ -24,7 +27,7 @@ int main(void) printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da)); da = daResize(da); - if (!da) goto cleanup; + if (!da) goto exit; printf("%zu %zu %zu\n", daSize(da), daCap(da), daType(da)); printf("DA2 -----\n"); @@ -36,7 +39,7 @@ int main(void) for (size_t i = 0; i < N; ++i) { daAppend(da2, "AAA"); - if (errno == 1) goto cleanup; + if (errno == 1) goto exit; } printf("%s%s\n", da2[0], da2[1]); @@ -48,10 +51,8 @@ int main(void) daAppend(da3, 420.420); printf("%.2f:%.3f\n", da3[0], da3[1]); -cleanup: - daFree(da3); - daFree(da2); - daFree(da); +exit: + daDeinitGC(); return 0; }