Paste: garbage collector

Author: goren
Mode: c
Date: Sat, 27 Jan 2024 22:52:42
Plain Text |
/* The following software is licensed under the GPL-3.0 license and created by Goren Barak. */

#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;

/* NOTE: you can use if (error) { ... } to check if there is an error. */
static Error error = NONE;

typedef struct Gc {
  void    **ptrs;       /* The pointers to the actual data or NULL if the data is a reference to an index on here. */
  uint32_t *rcs;        /* The reference counter for the data on this index in ptrs. */
  
  size_t len; /* The length of ptrs, references, and rcs (they have the same length). */
  size_t cap; /* The maximum capacity, will be doubled if reached. */
} Gc;

void
Gc_new(Gc *self)
{
  self->cap        = 256;
  void *ptr        = malloc((sizeof(void*) * 256) + (sizeof(uint32_t) * 256)); /* This allocates a grand total of 3072 bytes. */
  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

Summary:
Author:
Mode:
Body: