combine, union. WIP because reference-counting is broken

This commit is contained in:
Tony Garnock-Jones 2015-07-12 17:46:08 -04:00
parent 039ec0e4bd
commit b94668585f
7 changed files with 479 additions and 105 deletions

View File

@ -221,33 +221,101 @@ tt_node_ptr_t tt_dict_remove(tt_arena_t *a,
}
}
void tt_dict_foreach1(tt_arena_t *a,
tt_node_ptr_t n,
void *context,
void (*f)(void *context, tt_atom_t key, tt_node_ptr_t trie))
int tt_dict_foreach1(tt_arena_t *a,
tt_node_ptr_t n,
void *context,
int (*f)(void *context, tt_atom_t key, tt_node_ptr_t trie))
{
switch (tt_ptr_tag(n)) {
case TT_TAG_LEAF: {
f(context, TT_LEAF_ATOM(a,n), TT_LEAF_TRIE(a,n));
break;
return f(context, TT_LEAF_ATOM(a,n), TT_LEAF_TRIE(a,n));
}
case TT_TAG_NODE: {
tt_dict_foreach1(a, TT_NODE_ZERO(a,n), context, f);
tt_dict_foreach1(a, TT_NODE_ONE(a,n), context, f);
break;
if (!tt_dict_foreach1(a, TT_NODE_ZERO(a,n), context, f)) return 0;
return tt_dict_foreach1(a, TT_NODE_ONE(a,n), context, f);
}
default:
assert(0);
}
}
void tt_dict_foreach(tt_arena_t *a,
tt_node_ptr_t t,
void *context,
void (*f)(void *, tt_atom_t key, tt_node_ptr_t trie))
int tt_dict_foreach(tt_arena_t *a,
tt_node_ptr_t t,
void *context,
int (*f)(void *, tt_atom_t key, tt_node_ptr_t trie))
{
if (!TT_EMPTY_DICT_P(t)) {
if (TT_EMPTY_DICT_P(t)) {
return 1;
} else {
assert(tt_ptr_tag(t) == TT_TAG_DICT);
tt_dict_foreach1(a, TT_DICT_ROOT(a,t), context, f);
return tt_dict_foreach1(a, TT_DICT_ROOT(a,t), context, f);
}
}
tt_node_ptr_t tt_dictset_union(tt_arena_t *a, tt_node_ptr_t s1, tt_node_ptr_t s2) {
tt_node_ptr_t result = TT_NO_PTR; /* grab'd */
int f(void *context, tt_atom_t key, tt_node_ptr_t ignored_trie) {
tt_node_ptr_t new_result = tt_grab(a, tt_dict_set(a, result, key, TT_EMPTY));
tt_drop(a, result);
result = new_result;
return !TT_NO_PTR_P(result);
}
if (tt_dict_size(a, s1) < tt_dict_size(a, s2)) {
tt_node_ptr_t tmp = s2;
s2 = s1;
s1 = tmp;
}
/* Now s1 is larger, s2 is smaller. */
result = tt_grab(a, s1);
tt_dict_foreach(a, s2, NULL, f);
return result;
}
tt_node_ptr_t tt_dictset_intersection(tt_arena_t *a, tt_node_ptr_t s1, tt_node_ptr_t s2) {
tt_node_ptr_t result = TT_NO_PTR; /* grab'd */
int f(void *context, tt_atom_t key, tt_node_ptr_t ignored_trie) {
if (!TT_NO_PTR_P(tt_dict_get(a, s1, key))) {
tt_node_ptr_t new_result = tt_grab(a, tt_dict_set(a, result, key, TT_EMPTY));
tt_drop(a, result);
result = new_result;
}
return !TT_NO_PTR_P(result);
}
if (tt_dict_size(a, s1) < tt_dict_size(a, s2)) {
tt_node_ptr_t tmp = s2;
s2 = s1;
s1 = tmp;
}
/* Now s1 is larger, s2 is smaller. */
result = TT_EMPTY_DICT;
tt_dict_foreach(a, s2, NULL, f);
return result;
}
tt_node_ptr_t tt_dictset_difference(tt_arena_t *a, tt_node_ptr_t s1, tt_node_ptr_t s2) {
tt_node_ptr_t result = TT_NO_PTR;
if (tt_dict_size(a, s1) < tt_dict_size(a, s2)) {
int f(void *context, tt_atom_t key, tt_node_ptr_t ignored_trie) {
if (!TT_NO_PTR_P(tt_dict_get(a, s2, key))) {
tt_node_ptr_t new_result = tt_grab(a, tt_dict_set(a, result, key, TT_EMPTY));
tt_drop(a, result);
result = new_result;
}
return !TT_NO_PTR_P(result);
}
result = TT_EMPTY_DICT;
tt_dict_foreach(a, s1, NULL, f);
} else {
int f(void *context, tt_atom_t key, tt_node_ptr_t ignored_trie) {
tt_node_ptr_t new_result = tt_grab(a, tt_dict_remove(a, result, key));
tt_drop(a, result);
result = new_result;
return !TT_NO_PTR_P(result);
}
result = tt_grab(a, s1);
tt_dict_foreach(a, s2, NULL, f);
}
return result;
}

View File

@ -27,10 +27,19 @@ extern tt_node_ptr_t tt_dict_remove(tt_arena_t *a,
tt_node_ptr_t t,
tt_atom_t key);
extern void tt_dict_foreach(tt_arena_t *a,
tt_node_ptr_t t,
void *context,
void (*f)(void *, tt_atom_t key, tt_node_ptr_t trie));
/* Returns 1 if it examined the whole dict; 0 if it was aborted early */
extern int tt_dict_foreach(tt_arena_t *a,
tt_node_ptr_t t,
void *context,
/* Return 1 to continue the loop; 0 to abort it. */
int (*f)(void *, tt_atom_t key, tt_node_ptr_t trie));
/* Dictsets map to TT_EMPTY to indicate a *present* key (and
implicitly to TT_NO_PTR to indicate an *absent* key). */
/* THESE ALL RETURN grab'd RESULTS */
extern tt_node_ptr_t tt_dictset_union(tt_arena_t *a, tt_node_ptr_t s1, tt_node_ptr_t s2);
extern tt_node_ptr_t tt_dictset_intersection(tt_arena_t *a, tt_node_ptr_t s1, tt_node_ptr_t s2);
extern tt_node_ptr_t tt_dictset_difference(tt_arena_t *a, tt_node_ptr_t s1, tt_node_ptr_t s2);
#ifdef __cplusplus
}

67
main.c
View File

@ -6,6 +6,7 @@
#include "fasthash.h"
#include "treetrie.h"
#include "critbit.h"
#include "route.h"
static void atom_incref(void *atom_context, tt_arena_t *a, tt_atom_t atom) {
/* printf("incref %u\n", atom); */
@ -29,19 +30,19 @@ int main0(int argc, char *argv[]) {
tt_drop(&a, prev);
/* tt_arena_flush(&a); */
/* printf("---------------------------------------- AFTER DROP of %d:\n", prev); */
/* tt_dump_arena(&a); */
/* tt_dump_arena(&a, 1); */
prev = TT_EMPTY;
/* printf("======================================== LOOP ITERATION %d\n", outer); */
/* tt_dump_arena_summary(&a); */
for (i = 0; i < 1000000; i++) {
tt_node_ptr_t leaf = tt_cons_leaf(&a, TT_EMPTY, 1001);
tt_node_ptr_t curr = tt_cons_node(&a, 0, leaf, prev);
/* tt_dump_arena(&a); */
/* tt_dump_arena(&a, 1); */
prev = curr;
}
}
/* tt_dump_arena(&a); */
/* tt_dump_arena(&a, 1); */
tt_grab(&a, prev);
tt_drop(&a, prev);
/* tt_arena_flush(&a); */
@ -51,11 +52,12 @@ int main0(int argc, char *argv[]) {
return EXIT_SUCCESS;
}
static void dump_mapping(void *context, tt_atom_t key, tt_node_ptr_t trie) {
static int dump_mapping(void *context, tt_atom_t key, tt_node_ptr_t trie) {
printf(" -- %u --> %u/%u\n", key, tt_ptr_idx(trie), tt_ptr_tag(trie));
return 1;
}
int main(int argc, char *argv[]) {
int main1(int argc, char *argv[]) {
tt_arena_t a;
tt_node_ptr_t curr = TT_EMPTY_DICT;
int i;
@ -63,13 +65,13 @@ int main(int argc, char *argv[]) {
setbuf(stdout, NULL);
tt_arena_init(&a, NULL, atom_incref, atom_decref);
/* tt_dump_arena(&a); */
/* tt_dump_arena(&a, 1); */
for (i = 0; i < 1000000; i++) {
tt_node_ptr_t next = tt_grab(&a, tt_dict_set(&a, curr, i, TT_EMPTY));
tt_drop(&a, curr);
curr = next;
/* printf("\nAfter i=%d...\n", i); */
/* tt_dump_arena(&a); */
/* tt_dump_arena(&a, 1); */
}
/* for (i = 0; i < 1000000; i++) { */
@ -83,16 +85,63 @@ int main(int argc, char *argv[]) {
tt_ptr_idx(curr),
tt_ptr_tag(curr),
TT_DICT_SIZE(&a, curr));
/* tt_dump_arena(&a); */
/* tt_dump_arena(&a, 1); */
/* tt_dict_foreach(&a, curr, NULL, dump_mapping); */
tt_drop(&a, curr);
curr = TT_NO_PTR;
/* tt_arena_flush(&a); */
/* tt_dump_arena(&a); */
/* tt_dump_arena(&a, 1); */
tt_dump_arena_summary(&a);
tt_arena_done(&a);
return EXIT_SUCCESS;
}
int main(int argc, char *argv[]) {
tt_arena_t a;
tt_node_ptr_t a_set;
tt_node_ptr_t b_set;
setbuf(stdout, NULL);
tt_arena_init(&a, NULL, atom_incref, atom_decref);
a_set = tt_dict_singleton(&a, 'A', TT_EMPTY);
b_set = tt_dict_singleton(&a, 'B', TT_EMPTY);
{
tt_node_ptr_t A =
tt_grab(&a,
tt_prepend_path(&a, TT_BOS,
tt_prepend_path(&a, 'A',
tt_prepend_path(&a, TT_EOS,
tt_begin_path(&a, a_set)))));
printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A));
tt_dump_arena(&a, 0);
tt_node_ptr_t B =
tt_grab(&a,
tt_prepend_path(&a, TT_BOS,
tt_prepend_path(&a, 'B',
tt_prepend_path(&a, TT_EOS,
tt_begin_path(&a, b_set)))));
printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B));
tt_dump_arena(&a, 0);
tt_node_ptr_t C = tt_trie_union(&a, A, B);
tt_drop(&a, A);
tt_drop(&a, B);
printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C));
tt_dump_arena(&a, 0);
putchar('\n');
tt_dump_routingtable(&a, C, 0);
tt_drop(&a, C);
}
putchar('\n');
tt_arena_flush(&a);
tt_dump_arena(&a, 0);
/* tt_dump_arena_summary(&a); */
tt_arena_done(&a);
return EXIT_SUCCESS;
}

350
route.c
View File

@ -49,17 +49,17 @@ static inline tt_node_ptr_t runwildseq(tt_arena_t *a, tt_node_ptr_t r) {
}
}
static inline tt_node_ptr_t rlookup(tt_arena_t *a,
tt_node_ptr_t r,
tt_atom_t key)
static inline tt_node_ptr_t rlookup_dict(tt_arena_t *a,
tt_node_ptr_t wild,
tt_node_ptr_t others,
tt_atom_t key)
{
tt_node_ptr_t result;
assert(tt_ptr_tag(r) == TT_TAG_BRANCH);
result = tt_dict_get(a, TT_BRANCH_OTHERS(a,r), key);
result = tt_dict_get(a, others, key);
if (!TT_NO_PTR_P(result)) {
return result;
}
result = TT_BRANCH_WILDCARD(a,r);
result = wild;
switch (key) {
case TT_BOS: return rwildseq(a, result);
case TT_EOS: return runwildseq(a, result);
@ -67,6 +67,47 @@ static inline tt_node_ptr_t rlookup(tt_arena_t *a,
}
}
static inline tt_node_ptr_t rlookup(tt_arena_t *a,
tt_node_ptr_t r,
tt_atom_t key)
{
assert(tt_ptr_tag(r) == TT_TAG_BRANCH);
return rlookup_dict(a, TT_BRANCH_WILDCARD(a,r), TT_BRANCH_OTHERS(a,r), key);
}
static inline tt_node_ptr_t rupdate_dict(tt_arena_t *a,
tt_node_ptr_t old_wild, /* trie */
tt_node_ptr_t old_others, /* dict */
tt_atom_t key,
tt_node_ptr_t k) /* trie */
{
assert(key != TT_WILD);
assert(TT_EMPTY_DICT_P(old_others) || tt_ptr_tag(old_others) == TT_TAG_DICT);
#define OTHERS_SANS_KEY() (tt_dict_remove(a, old_others, key))
#define OTHERS_WITH_KEY() (tt_dict_set(a, old_others, key, k))
switch (key) {
case TT_BOS:
if (tt_ptr_tag(k) == TT_TAG_TAIL) {
return (TT_TAIL_TRIE(a,k) == old_wild) ? OTHERS_SANS_KEY() : OTHERS_WITH_KEY();
} else {
return TT_EMPTY_P(k) ? OTHERS_SANS_KEY() : OTHERS_WITH_KEY();
}
case TT_EOS:
if (tt_ptr_tag(old_wild) == TT_TAG_TAIL) {
return (TT_TAIL_TRIE(a,old_wild) == k) ? OTHERS_SANS_KEY() : OTHERS_WITH_KEY();
} else {
return TT_EMPTY_P(k) ? OTHERS_SANS_KEY() : OTHERS_WITH_KEY();
}
default:
return (k == old_wild) ? OTHERS_SANS_KEY() : OTHERS_WITH_KEY();
}
#undef OTHERS_SANS_KEY
#undef OTHERS_WITH_KEY
}
static inline tt_node_ptr_t rupdate(tt_arena_t *a,
tt_node_ptr_t r0, /* branch */
tt_atom_t key,
@ -76,73 +117,248 @@ static inline tt_node_ptr_t rupdate(tt_arena_t *a,
if (TT_EMPTY_P(r0)) {
return rseq(a, key, k);
} else {
tt_node_ptr_t old_wild;
tt_node_ptr_t old_others;
tt_node_ptr_t new_others;
assert(tt_ptr_tag(r0) == TT_TAG_BRANCH);
old_wild = TT_BRANCH_WILDCARD(a,r0);
old_others = TT_BRANCH_OTHERS(a,r0);
#define R0_SANS_KEY() (rbranch(a, old_wild, RET_IF_NO_PTR(tt_dict_remove(a, old_others, key))))
#define R0_WITH_KEY() (rbranch(a, old_wild, RET_IF_NO_PTR(tt_dict_set(a, old_others, key, k))))
switch (key) {
case TT_BOS:
if (tt_ptr_tag(k) == TT_TAG_TAIL) {
return (TT_TAIL_TRIE(a,k) == old_wild) ? R0_SANS_KEY() : R0_WITH_KEY();
} else {
return TT_EMPTY_P(k) ? R0_SANS_KEY() : R0_WITH_KEY();
}
case TT_EOS:
if (tt_ptr_tag(old_wild) == TT_TAG_TAIL) {
return (TT_TAIL_TRIE(a,old_wild) == k) ? R0_SANS_KEY() : R0_WITH_KEY();
} else {
return TT_EMPTY_P(k) ? R0_SANS_KEY() : R0_WITH_KEY();
}
default:
return (k == old_wild) ? R0_SANS_KEY() : R0_WITH_KEY();
}
#undef R0_SANS_KEY
#undef R0_WITH_KEY
new_others = rupdate_dict(a, TT_BRANCH_WILDCARD(a,r0), TT_BRANCH_OTHERS(a,r0), key, k);
return rbranch(a, TT_BRANCH_WILDCARD(a,r0), RET_IF_NO_PTR(new_others));
}
}
/* static tt_node_ptr_t combine(tt_arena_t *a, */
/* tt_node_ptr_t r1, */
/* tt_node_ptr_t r2, */
/* int left_empty_keep, */
/* int right_empty_keep, */
/* int left_base_keep, */
/* int right_base_keep, */
/* void *f_context, */
/* tt_node_ptr_t (*f)(void *f_context, tt_node_ptr_t r1, tt_node_ptr_t r2)) */
/* { */
/* tt_node_ptr_t g(tt_node_ptr_t r1, tt_node_ptr_t r2) { */
/* tt_tag_t t1, t2; */
static inline tt_node_ptr_t expand(tt_arena_t *a, tt_node_ptr_t tailnode) {
tt_node_ptr_t others = RET_IF_NO_PTR(tt_dict_singleton(a, TT_EOS, TT_TAIL_TRIE(a,tailnode)));
return rbranch(a, tailnode, others);
}
/* if (TT_EMPTY_P(r1)) { */
/* return left_empty_keep ? r2 : TT_EMPTY; */
/* } */
/* if (TT_EMPTY_P(r2)) { */
/* return right_empty_keep ? r1 : TT_EMPTY; */
/* } */
/* N.B. Returns a tt_grab'd result. */
tt_node_ptr_t tt_trie_combine(tt_arena_t *a,
tt_node_ptr_t r1,
tt_node_ptr_t r2,
int left_empty_keep,
int right_empty_keep,
int left_base_keep,
int right_base_keep,
void *f_context,
/* Should return a tt_grab'd result. */
tt_node_ptr_t (*f)(void *f_context,
tt_node_ptr_t r1,
tt_node_ptr_t r2))
{
/* N.B. Returns a tt_grab'd result. */
tt_node_ptr_t g(tt_node_ptr_t r1, tt_node_ptr_t r2) {
tt_tag_t t1, t2;
/* t1 = tt_ptr_tag(r1); */
/* t2 = tt_ptr_tag(r2); */
if (TT_EMPTY_P(r1)) {
return left_empty_keep ? tt_grab(a, r2) : TT_EMPTY;
}
if (TT_EMPTY_P(r2)) {
return right_empty_keep ? tt_grab(a, r1) : TT_EMPTY;
}
/* if (t1 == TT_TAG_TAIL) { */
/* if (t2 == TT_TAG_TAIL) { */
/* return rwildseq(a, RET_IF_NO_PTR(g(TT_TAIL_TRIE(a,r1), TT_TAIL_TRIE(a,r2)))); */
/* } else { */
/* ....HERE */
/* } */
t1 = tt_ptr_tag(r1);
t2 = tt_ptr_tag(r2);
/* switch (tt_ptr_tag(r1)) { */
/* default: */
/* abort(); */
/* } */
/* } */
if (t1 == TT_TAG_BRANCH && t2 == TT_TAG_BRANCH) {
tt_node_ptr_t w1 = TT_BRANCH_WILDCARD(a,r1);
tt_node_ptr_t w2 = TT_BRANCH_WILDCARD(a,r2);
tt_node_ptr_t dict1 = TT_BRANCH_OTHERS(a,r1);
tt_node_ptr_t dict2 = TT_BRANCH_OTHERS(a,r2);
tt_node_ptr_t result_wild = TT_NO_PTR; /* grab'd */
tt_node_ptr_t result_others = TT_EMPTY_DICT; /* grab'd */
tt_node_ptr_t result = TT_NO_PTR; /* grab'd */
int ok = 1;
/* return g(r1, r2); */
/* } */
int examine_key(void *examine_key_context, tt_atom_t key, tt_node_ptr_t ignored_trie) {
tt_node_ptr_t trie1, trie2; /* Looked up in r1 and r2 */
tt_node_ptr_t new_trie; /* Combination of trie1 and trie2 */
tt_node_ptr_t new_result_others; /* Updated dictionary with key---new_trie association */
trie1 = tt_grab(a, rlookup_dict(a, w1, dict1, key));
if (TT_NO_PTR_P(trie1)) return 0;
trie2 = tt_grab(a, rlookup_dict(a, w2, dict2, key));
if (TT_NO_PTR_P(trie2)) {
tt_drop(a, trie1);
return 0;
}
new_trie = g(trie1, trie2); /* already grabbed */
if (TT_NO_PTR_P(new_trie)) {
tt_drop(a, trie1);
tt_drop(a, trie2);
return 0;
}
new_result_others = tt_grab(a, rupdate_dict(a, result_wild, result_others, key, new_trie));
if (TT_NO_PTR_P(new_result_others)) {
tt_drop(a, trie1);
tt_drop(a, trie2);
tt_drop(a, new_trie);
return 0;
}
tt_drop(a, result_others);
result_others = new_result_others;
return 1;
}
if (!TT_EMPTY_P(w1) && !TT_EMPTY_P(w2)) {
/* Two wildcards - worst case. Must loop over both dictionaries. */
result_wild = g(w1, w2);
ok = ok && tt_dict_foreach(a, dict1, NULL, examine_key);
ok = ok && tt_dict_foreach(a, dict2, NULL, examine_key);
} else if ((!TT_EMPTY_P(w1)) ||
(TT_EMPTY_P(w2) &&
(tt_dict_size(a, dict1) >= tt_dict_size(a, dict2)))) {
/* Either a wildcard on the left, or no wildcard at all but the left is larger */
result_wild = tt_grab(a, w1);
result_others = left_base_keep ? tt_grab(a, dict1) : TT_EMPTY_DICT;
ok = ok && tt_dict_foreach(a, dict2, NULL, examine_key);
} else {
/* Either a wildcard on the right, or no wildcard at all but the right is larger */
result_wild = tt_grab(a, w2);
result_others = right_base_keep ? tt_grab(a, dict2) : TT_EMPTY_DICT;
ok = ok && tt_dict_foreach(a, dict1, NULL, examine_key);
}
if (ok) {
result = tt_grab(a, rbranch(a, result_wild, result_others));
}
tt_drop(a, result_wild);
tt_drop(a, result_others);
return result;
}
if (t1 == TT_TAG_TAIL) {
if (t2 == TT_TAG_TAIL) {
tt_node_ptr_t combined = RET_IF_NO_PTR(g(TT_TAIL_TRIE(a,r1), TT_TAIL_TRIE(a,r2)));
tt_node_ptr_t result = tt_grab(a, rwildseq(a, combined));
tt_drop(a, combined);
return result;
} else {
tt_node_ptr_t r2_expanded = tt_grab(a, RET_IF_NO_PTR(expand(a, r2)));
tt_node_ptr_t result = g(r1, r2_expanded);
tt_drop(a, r2_expanded);
return result;
}
} else if (t2 == TT_TAG_TAIL) {
tt_node_ptr_t r1_expanded = tt_grab(a, RET_IF_NO_PTR(expand(a, r1)));
tt_node_ptr_t result = g(r1_expanded, r2);
tt_drop(a, r1_expanded);
return result;
}
if (t1 == TT_TAG_OK || t2 == TT_TAG_OK) {
return f(f_context, r1, r2);
}
/* There is no legitimate combination of tags that should let us get here. */
assert(0);
}
/* No need for tt_grab here - g has already done that for us */
return g(r1, r2);
}
tt_node_ptr_t tt_trie_union(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2) {
tt_node_ptr_t f_union(void *f_context, tt_node_ptr_t r1, tt_node_ptr_t r2) {
tt_tag_t t1 = tt_ptr_tag(r1);
tt_tag_t t2 = tt_ptr_tag(r2);
if (t1 != TT_TAG_OK) {
/* t2 must be ok. */
return tt_grab(a, r2);
} else if (t2 != TT_TAG_OK) {
return tt_grab(a, r1);
} else {
tt_node_ptr_t s = RET_IF_NO_PTR(tt_dictset_union(a, TT_OK_DICT(a,r1), TT_OK_DICT(a,r2)));
tt_node_ptr_t result = tt_cons_ok(a, s);
tt_drop(a, s);
return tt_grab(a, result);
}
}
return tt_trie_combine(a, r1, r2, 1, 1, 1, 1, NULL, f_union);
}
tt_node_ptr_t tt_begin_path(tt_arena_t *a, tt_node_ptr_t ok_dict) {
return tt_cons_ok(a, ok_dict);
}
tt_node_ptr_t tt_prepend_path(tt_arena_t *a, tt_atom_t tok, tt_node_ptr_t tail) {
if (tok == TT_WILD) {
return rwild(a, tail);
} else {
return rseq(a, tok, tail);
}
}
void print_indent(int spaces) {
while (spaces--) {
putchar(' ');
}
}
void tt_dump_routingtable(tt_arena_t *a, tt_node_ptr_t r, int initial_indent) {
void walk(int indent, tt_node_ptr_t r) {
switch (tt_ptr_tag(r)) {
case TT_TAG_TAIL:
printf(" ...>");
walk(indent + 5, TT_TAIL_TRIE(a, r));
break;
case TT_TAG_OK: {
int need_space = 0;
int pkey(void *context, tt_atom_t key, tt_node_ptr_t ignored_trie) {
if (need_space) {
putchar(' ');
} else {
need_space = 1;
}
printf("%d", key);
return 1;
}
fputs(" {", stdout);
tt_dict_foreach(a, TT_OK_DICT(a, r), NULL, pkey);
putchar('}');
break;
}
case TT_TAG_BRANCH: {
int need_sep = 0;
int pedge(void *context, tt_atom_t key, tt_node_ptr_t node) {
char keystr[256]; /* not very tight */
if (need_sep) {
putchar('\n');
print_indent(indent);
} else {
need_sep = 1;
}
keystr[sizeof(keystr) - 1] = '\0';
switch (key) {
case TT_WILD: snprintf(keystr, sizeof(keystr) - 1, ""); break;
case TT_BOS: snprintf(keystr, sizeof(keystr) - 1, " <"); break;
case TT_EOS: snprintf(keystr, sizeof(keystr) - 1, " >"); break;
case TT_BOC: snprintf(keystr, sizeof(keystr) - 1, " {"); break;
case TT_EOC: snprintf(keystr, sizeof(keystr) - 1, " }"); break;
default:
snprintf(keystr, sizeof(keystr) - 1, " %d", key);
}
fputs(keystr, stdout);
walk(indent + strlen(keystr), node);
return 1;
}
if (!TT_EMPTY_P(TT_BRANCH_WILDCARD(a, r))) {
pedge(NULL, TT_WILD, TT_BRANCH_WILDCARD(a, r));
}
tt_dict_foreach(a, TT_BRANCH_OTHERS(a, r), NULL, pedge);
if (!need_sep) {
printf(" ::: no edges!");
}
break;
}
case TT_TAG_SPECIAL:
if (TT_EMPTY_P(r)) {
printf(" ::: nothing");
break;
}
/* fall through */
default:
printf("?!?!?! %x", (unsigned int) r);
break;
}
}
walk(initial_indent, r);
putchar('\n');
}

23
route.h
View File

@ -11,6 +11,29 @@
#define TT_BOC ((tt_atom_t) -7) /* Beginning of capture */
#define TT_EOC ((tt_atom_t) -9) /* End of capture */
/* N.B. Returns a tt_grab'd result. */
extern tt_node_ptr_t tt_trie_combine(tt_arena_t *a,
tt_node_ptr_t r1,
tt_node_ptr_t r2,
int left_empty_keep,
int right_empty_keep,
int left_base_keep,
int right_base_keep,
void *f_context,
/* Should return a tt_grab'd result. */
tt_node_ptr_t (*f)(void *f_context,
tt_node_ptr_t r1,
tt_node_ptr_t r2));
/* N.B. Returns a tt_grab'd result. */
extern tt_node_ptr_t tt_trie_union(tt_arena_t *a, tt_node_ptr_t r1, tt_node_ptr_t r2);
/* These return ungrab'd */
extern tt_node_ptr_t tt_begin_path(tt_arena_t *a, tt_node_ptr_t ok_dict);
extern tt_node_ptr_t tt_prepend_path(tt_arena_t *a, tt_atom_t tok, tt_node_ptr_t tail);
extern void tt_dump_routingtable(tt_arena_t *a, tt_node_ptr_t r, int initial_indent);
// TODO move to the right place
#ifdef __cplusplus
extern "C" {

View File

@ -177,7 +177,7 @@ static int tt_grow(tt_arena_t *a) {
unsigned int new_table_length = old_table_length << 1;
/* printf("PREGROW\n"); */
/* tt_dump_arena(a); */
/* tt_dump_arena(a, 1); */
{
tt_hashtable_entry_t *new_table = calloc(new_table_length, sizeof(a->table[0]));
@ -255,18 +255,23 @@ void tt_dump_arena_summary(tt_arena_t *a) {
printf("free_count: %u\n", a->free_count);
}
void tt_dump_arena(tt_arena_t *a) {
void tt_dump_arena(tt_arena_t *a, int show_free_chain) {
tt_dump_arena_summary(a);
printf("free_chain:");
{
if (show_free_chain) {
int chain_counter = 0;
tt_node_idx_t fp = a->free_chain.head;
printf("free_chain:");
while (fp != TT_NO_IDX) {
if ((chain_counter % 10) == 0) {
printf("\n ");
}
printf(" %d", fp);
fp = a->headers[fp].next_free;
chain_counter++;
}
printf("\n");
}
printf("\n");
{
int i;
@ -308,10 +313,10 @@ void tt_dump_arena(tt_arena_t *a) {
tt_ptr_tag(a->nodes[n].b));
break;
case TT_TAG_LEAF:
printf("leaf %u/%u %u\n",
printf("leaf %u/%u %d\n",
tt_ptr_idx(a->nodes[n].a),
tt_ptr_tag(a->nodes[n].a),
a->nodes[n].b);
(int) a->nodes[n].b);
break;
case TT_TAG_NODE:
printf("node index %d, %u/%u %u/%u\n",
@ -427,7 +432,9 @@ static void recycle_node(tt_arena_t *a, tt_node_ptr_t p) {
inline tt_node_ptr_t tt_grab(tt_arena_t *a, tt_node_ptr_t p) {
tt_node_idx_t i = tt_ptr_idx(p);
if (tt_ptr_tag(p) != TT_TAG_SPECIAL && a->headers[i].inuse.refcount < TT_REFCOUNT_LIMIT) {
tt_tag_t t = tt_ptr_tag(p);
if (t != TT_TAG_INVALID && t != TT_TAG_SPECIAL
&& a->headers[i].inuse.refcount < TT_REFCOUNT_LIMIT) {
a->headers[i].inuse.refcount++;
}
return p;
@ -435,7 +442,9 @@ inline tt_node_ptr_t tt_grab(tt_arena_t *a, tt_node_ptr_t p) {
inline void tt_drop(tt_arena_t *a, tt_node_ptr_t p) {
tt_node_idx_t i = tt_ptr_idx(p);
if (tt_ptr_tag(p) != TT_TAG_SPECIAL && a->headers[i].inuse.refcount < TT_REFCOUNT_LIMIT) {
tt_tag_t t = tt_ptr_tag(p);
if (t != TT_TAG_INVALID && t != TT_TAG_SPECIAL
&& a->headers[i].inuse.refcount < TT_REFCOUNT_LIMIT) {
/* printf("++++++++++++++++++++++++++++++ dropping %d\n", i); */
if (--(a->headers[i].inuse.refcount) == 0) {
recycle_node(a, p);

View File

@ -109,7 +109,7 @@ extern int tt_arena_init(tt_arena_t *a,
extern void tt_arena_done(tt_arena_t *a);
extern void tt_dump_arena_summary(tt_arena_t *a);
extern void tt_dump_arena(tt_arena_t *a);
extern void tt_dump_arena(tt_arena_t *a, int show_free_chain);
extern void tt_arena_flush(tt_arena_t *a);