Paste: garbage collector
Author: | goren |
Mode: | c |
Date: | Sat, 27 Jan 2024 22:52:42 |
Plain Text |
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#ifndef NO_FETCH_MACRO
#define fetch(T, gc, x) *((T*)Gc_fetch(gc, x))
#endif
typedef enum {
NONE,
NOT_ENOUGH_MEMORY_ALLOC,
NOT_ENOUGH_MEMORY_HEADER,
} Error;
static Error error = NONE;
typedef struct Gc {
void **ptrs;
uint32_t *rcs;
size_t len;
size_t cap;
} Gc;
void
Gc_new(Gc *self)
{
self->cap = 256;
void *ptr = malloc((sizeof(void*) * 256) + (sizeof(uint32_t) * 256));
if (ptr == NULL) {
error == NOT_ENOUGH_MEMORY_HEADER;
}
self->ptrs = ptr;
self->rcs = ptr + (sizeof(void*) * 256);
self->len = 0;
}
uint32_t
Gc_allocate(Gc *self, size_t size)
{
if (self->len+1 > self->cap) {
self->cap *= 2;
if (!realloc(self->ptrs, (sizeof(void*) * self->cap) + ((sizeof(uint32_t) * self->cap)))) {
error = NOT_ENOUGH_MEMORY_HEADER;
}
}
void *ptr = malloc(size);
if (ptr == NULL) {
error = NOT_ENOUGH_MEMORY_ALLOC;
}
self->ptrs[self->len] = ptr;
self->rcs[self->len] = 1;
return self->len++;
}
uint32_t
Gc_ref(Gc *self, uint32_t id)
{
self->rcs[id] += 1;
return id;
}
void*
Gc_fetch(Gc *self, uint32_t id)
{
void* ptr = self->ptrs[id];
if (ptr != NULL) {
return ptr;
} else {
printf("ERROR: tried to access deleted variable.\n");
exit(-1);
}
}
void
Gc_drop(Gc *self, uint32_t id)
{
self->rcs[id] -= 1;
if (self->rcs[id] == 0) {
free(self->ptrs[id]);
self->ptrs[id] = NULL;
}
}
New Annotation