diff --git a/Makefile b/Makefile index a0d7846..42fdfe9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: t t: *.c - $(CC) -Wall -Os -o $@ -g *.c + $(CC) -Wall -O0 -o $@ -g *.c clean: rm -f t diff --git a/critbit.c b/critbit.c index c910dd4..c0606f9 100644 --- a/critbit.c +++ b/critbit.c @@ -54,7 +54,8 @@ static int set_walk(tt_arena_t *a, tt_atom_t key, tt_node_ptr_t trie, tt_node_ptr_t n, - tt_node_ptr_t *result) + tt_node_ptr_t *result, + int *added_count) { switch (tt_ptr_tag(n)) { case TT_TAG_LEAF: { @@ -71,6 +72,7 @@ static int set_walk(tt_arena_t *a, } else { int leading_zeros = __builtin_clz(differences); int first_differing_bit = (8 * sizeof(differences)) - leading_zeros - 1; + *added_count = 1; return first_differing_bit; } } @@ -78,7 +80,7 @@ static int set_walk(tt_arena_t *a, int index = TT_NODE_INDEX(a, n); if (bit_ref(key, index)) { tt_node_ptr_t one = TT_NODE_ONE(a, n); - int first_differing_bit = set_walk(a, key, trie, one, result); + int first_differing_bit = set_walk(a, key, trie, one, result, added_count); if (first_differing_bit == -1) { if (*result == one) { *result = n; @@ -99,7 +101,7 @@ static int set_walk(tt_arena_t *a, } } else { tt_node_ptr_t zero = TT_NODE_ZERO(a, n); - int first_differing_bit = set_walk(a, key, trie, zero, result); + int first_differing_bit = set_walk(a, key, trie, zero, result, added_count); if (first_differing_bit == -1) { if (*result == zero) { *result = n; @@ -145,8 +147,9 @@ tt_node_ptr_t tt_dict_set(tt_arena_t *a, { tt_node_ptr_t old_root = TT_DICT_ROOT(a,t); + int added_count = 0; tt_node_ptr_t result = TT_NO_PTR; - int first_differing_bit = set_walk(a, key, trie, old_root, &result); + int first_differing_bit = set_walk(a, key, trie, old_root, &result, &added_count); if (first_differing_bit != -1) { result = splice_key(a, key, trie, first_differing_bit, old_root); } @@ -155,7 +158,7 @@ tt_node_ptr_t tt_dict_set(tt_arena_t *a, } else if (result == old_root) { return t; } else { - return tt_cons_dict(a, result, TT_DICT_SIZE(a,t) + 1); + return tt_cons_dict(a, result, TT_DICT_SIZE(a,t) + added_count); } } } @@ -210,11 +213,14 @@ tt_node_ptr_t tt_dict_remove(tt_arena_t *a, assert(tt_ptr_tag(t) == TT_TAG_DICT); { + tt_node_ptr_t old_root = TT_DICT_ROOT(a,t); int removed_count = 0; tt_node_ptr_t n = - RET_IF_NO_PTR(tt_dict_remove1(a, TT_DICT_ROOT(a,t), key, &removed_count)); + RET_IF_NO_PTR(tt_dict_remove1(a, old_root, key, &removed_count)); if (TT_EMPTY_DICT_P(n)) { return TT_EMPTY_DICT; + } else if (n == old_root) { + return t; } else { return tt_cons_dict(a, n, TT_DICT_SIZE(a,t) - removed_count); } diff --git a/main.c b/main.c index df5d6b5..d078f5e 100644 --- a/main.c +++ b/main.c @@ -107,9 +107,10 @@ int main(int argc, char *argv[]) { 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); + a_set = tt_grab(&a, tt_dict_singleton(&a, 'A', TT_EMPTY)); + b_set = tt_grab(&a, tt_dict_singleton(&a, 'B', TT_EMPTY)); + printf("\n============================================================ 1\n"); { tt_node_ptr_t A = tt_grab(&a, @@ -119,7 +120,7 @@ int main(int argc, char *argv[]) { tt_begin_path(&a, a_set))))); printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); tt_arena_flush(&a); - tt_dump_arena_dot(&a); + tt_dump_arena_dot("A", A, &a); tt_node_ptr_t B = tt_grab(&a, tt_prepend_path(&a, TT_BOS, @@ -127,23 +128,112 @@ int main(int argc, char *argv[]) { 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_arena_flush(&a); - tt_dump_arena_dot(&a); + tt_dump_arena_dot("B", B, &a); tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_arena_flush(&a); + tt_dump_arena_dot("Cpredrop", C, &a); tt_drop(&a, A); tt_drop(&a, B); printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); tt_arena_flush(&a); - tt_dump_arena_dot(&a); + tt_dump_arena_dot("Cpostdrop", C, &a); putchar('\n'); tt_dump_routingtable(&a, C, 0); tt_drop(&a, C); } - putchar('\n'); tt_arena_flush(&a); - tt_dump_arena_dot(&a); - /* tt_dump_arena_summary(&a); */ + tt_dump_arena_dot("after1", TT_NO_PTR, &a); + + printf("\n============================================================ 2\n"); + { + 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_arena_flush(&a); + tt_dump_arena_dot("A", A, &a); + tt_node_ptr_t B = + tt_grab(&a, + tt_prepend_path(&a, TT_BOS, + tt_prepend_path(&a, TT_WILD, + 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_dot("B", B, &a); + tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_arena_flush(&a); + tt_dump_arena_dot("Cpredrop", C, &a); + tt_drop(&a, A); + tt_drop(&a, B); + printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); + tt_arena_flush(&a); + tt_dump_arena_dot("Cpostdrop", C, &a); + putchar('\n'); + tt_dump_routingtable(&a, C, 0); + tt_drop(&a, C); + } + + printf("\n============================================================ 3\n"); + { + 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_arena_flush(&a); + tt_dump_arena_dot("A", A, &a); + tt_node_ptr_t B = tt_grab(&a, tt_prepend_path(&a, TT_WILD, tt_begin_path(&a, b_set))); + printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); + tt_dump_arena_dot("B", B, &a); + tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_arena_flush(&a); + tt_dump_arena_dot("Cpredrop", C, &a); + tt_drop(&a, A); + tt_drop(&a, B); + printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); + tt_arena_flush(&a); + tt_dump_arena_dot("Cpostdrop", C, &a); + putchar('\n'); + tt_dump_routingtable(&a, C, 0); + tt_drop(&a, C); + } + + printf("\n============================================================ 4\n"); + { + 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, + /* NB b_set below */ + tt_begin_path(&a, b_set))))); + printf("\nA node: %u/%u\n", tt_ptr_idx(A), tt_ptr_tag(A)); + tt_arena_flush(&a); + tt_dump_arena_dot("A", A, &a); + tt_node_ptr_t B = tt_grab(&a, tt_prepend_path(&a, TT_WILD, tt_begin_path(&a, b_set))); + printf("\nB node: %u/%u\n", tt_ptr_idx(B), tt_ptr_tag(B)); + tt_dump_arena_dot("B", B, &a); + tt_node_ptr_t C = tt_trie_union(&a, A, B); + tt_arena_flush(&a); + tt_dump_arena_dot("Cpredrop", C, &a); + tt_drop(&a, A); + tt_drop(&a, B); + printf("\nC node: %u/%u\n", tt_ptr_idx(C), tt_ptr_tag(C)); + tt_arena_flush(&a); + tt_dump_arena_dot("Cpostdrop", C, &a); + putchar('\n'); + tt_dump_routingtable(&a, C, 0); + tt_drop(&a, C); + } + + tt_arena_flush(&a); + tt_dump_arena_dot("afterAll", TT_NO_PTR, &a); /* expect a_set and b_set here */ tt_arena_done(&a); return EXIT_SUCCESS; diff --git a/route.c b/route.c index e0ca860..437a63f 100644 --- a/route.c +++ b/route.c @@ -179,18 +179,12 @@ tt_node_ptr_t tt_trie_combine(tt_arena_t *a, 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; - } + tt_drop(a, trie1); + tt_drop(a, trie2); + if (TT_NO_PTR_P(new_trie)) 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, new_trie); + if (TT_NO_PTR_P(new_result_others)) return 0; tt_drop(a, result_others); result_others = new_result_others; return 1; @@ -231,15 +225,15 @@ tt_node_ptr_t tt_trie_combine(tt_arena_t *a, 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); + 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; } } 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); + 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; } diff --git a/treetrie.c b/treetrie.c index 02d0c16..b663f9d 100644 --- a/treetrie.c +++ b/treetrie.c @@ -354,10 +354,16 @@ static void dump_dot_edge(tt_arena_t *a, tt_node_ptr_t p, int lr, char const *ed } } -void tt_dump_arena_dot(tt_arena_t *a) { +void tt_dump_arena_dot(char const *rootlabel, tt_node_ptr_t rootptr, tt_arena_t *a) { int i; printf("digraph Arena {\n"); + printf(" root [shape=box, label=\"%s\"];\n", rootlabel); + if (tt_ptr_tag(rootptr) != TT_TAG_INVALID && tt_ptr_tag(rootptr) != TT_TAG_SPECIAL) { + printf(" root -> i%u_%u;\n", + tt_ptr_idx(rootptr), + tt_ptr_tag(rootptr)); + } for (i = 0; i < a->table_length; i++) { tt_node_ptr_t p = a->table[i].ptr; tt_node_idx_t n = tt_ptr_idx(p); @@ -386,7 +392,7 @@ void tt_dump_arena_dot(tt_arena_t *a) { printf("label=\"branch"); break; case TT_TAG_LEAF: - printf("label=\"leaf a%d", (int) a->nodes[n].b); + printf("shape=underline,label=\"leaf a%d", (int) a->nodes[n].b); break; case TT_TAG_NODE: printf("label=\"node @%d", a->headers[n].inuse.index); @@ -399,7 +405,7 @@ void tt_dump_arena_dot(tt_arena_t *a) { assert(0); } /* printf(" #%u d%d r%d\"];\n", i, distance, a->headers[n].inuse.refcount); */ - printf(" r%d\"];\n", a->headers[n].inuse.refcount); + printf(" i%u r%d\"];\n", n, a->headers[n].inuse.refcount); switch (tt_ptr_tag(p)) { case TT_TAG_TAIL: dump_dot_edge(a, p, 0, "trie"); diff --git a/treetrie.h b/treetrie.h index 571c2a7..983b31c 100644 --- a/treetrie.h +++ b/treetrie.h @@ -110,7 +110,7 @@ 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, int show_free_chain); -extern void tt_dump_arena_dot(tt_arena_t *a); +extern void tt_dump_arena_dot(char const *rootlabel, tt_node_ptr_t rootptr, tt_arena_t *a); extern void tt_arena_flush(tt_arena_t *a);