134 lines
2.8 KiB
C
134 lines
2.8 KiB
C
#include "stack.c"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
#include "khash.h"
|
|
|
|
typedef int HEAP_KEY;
|
|
|
|
typedef enum {
|
|
TH_STRING, TH_ARRAY, TH_TABLE,
|
|
} TYC_HEAP_TYPE;
|
|
|
|
typedef struct {
|
|
TYC_HEAP_TYPE type;
|
|
union {
|
|
char* str;
|
|
// TODO - array and table
|
|
} value;
|
|
} HeapValue;
|
|
KHASH_MAP_INIT_INT64(HEAP, HeapValue)
|
|
|
|
typedef struct {
|
|
khash_t(HEAP) *items;
|
|
} Heap;
|
|
|
|
static void heap_init(Heap* h)
|
|
{
|
|
h->items = kh_init(HEAP);
|
|
}
|
|
|
|
static void heap_free_item(HeapValue value)
|
|
{
|
|
switch (value.type) {
|
|
case TH_STRING:
|
|
free(value.value.str);
|
|
break;
|
|
case TH_ARRAY:
|
|
abort(); // not implemented yet
|
|
break;
|
|
case TH_TABLE:
|
|
abort(); // not implemented yet
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void heap_finalize(Heap* h)
|
|
{
|
|
for (khiter_t k = kh_begin(h->items); k != kh_end(h->items); ++k) {
|
|
if (kh_exist(h->items, k)) {
|
|
HeapValue value = kh_value(h->items, k);
|
|
heap_free_item(value);
|
|
}
|
|
}
|
|
kh_destroy(HEAP, h->items);
|
|
}
|
|
|
|
static HEAP_KEY heap_add_string(Heap* h, const char* value)
|
|
{
|
|
int ret;
|
|
khiter_t k;
|
|
HEAP_KEY key;
|
|
|
|
do {
|
|
key = rand();
|
|
k = kh_get(HEAP, h->items, key);
|
|
} while (k != kh_end(h->items));
|
|
|
|
k = kh_put(HEAP, h->items, key, &ret);
|
|
kh_value(h->items, k) = (HeapValue) {
|
|
.type = TH_STRING,
|
|
.value = { .str = strdup(value) }
|
|
};
|
|
|
|
return key;
|
|
}
|
|
|
|
#include <stdio.h>
|
|
static TYC_RESULT heap_get_string(Heap* h, HEAP_KEY key, const char** value)
|
|
{
|
|
khiter_t k = kh_get(HEAP, h->items, key);
|
|
bool is_missing = (k == kh_end(h->items));
|
|
if (is_missing)
|
|
return T_ERR_HEAP_KEY_NOT_FOUND;
|
|
*value = kh_value(h->items, k).value.str;
|
|
return T_OK;
|
|
}
|
|
|
|
static size_t heap_size(Heap* h)
|
|
{
|
|
return kh_size(h->items);
|
|
}
|
|
|
|
//
|
|
// GC
|
|
//
|
|
|
|
KHASH_MAP_INIT_INT64(MARK, bool)
|
|
|
|
static void heap_gc(Heap* h, VALUE const* roots, size_t n_roots)
|
|
{
|
|
//
|
|
// mark
|
|
//
|
|
|
|
khash_t(MARK) *marked = kh_init(MARK);
|
|
|
|
for (size_t i = 0; i < n_roots; ++i) {
|
|
if (value_type(roots[i]) == TT_STRING) {
|
|
int ret;
|
|
uint32_t key = value_idx(roots[i]);
|
|
khiter_t k = kh_put(MARK, marked, key, &ret);
|
|
kh_value(marked, k) = true;
|
|
}
|
|
}
|
|
|
|
//
|
|
// sweep
|
|
//
|
|
|
|
for (khiter_t k = kh_begin(h->items); k != kh_end(h->items); ++k) {
|
|
if (kh_exist(h->items, k)) {
|
|
HEAP_KEY key = kh_key(h->items, k);
|
|
if (kh_get(MARK, marked, key) == kh_end(marked)) {
|
|
khiter_t kk = kh_get(HEAP, h->items, key);
|
|
heap_free_item(kh_value(h->items, kk));
|
|
kh_del(HEAP, h->items, kk);
|
|
}
|
|
}
|
|
}
|
|
|
|
kh_destroy(MARK, marked);
|
|
} |