| [a999c3f] | 1 | #include <seq.cvh>
|
|---|
| 2 | #include <stdlib.h>
|
|---|
| 3 | #include "treebuffer.h"
|
|---|
| 4 |
|
|---|
| 5 | struct Node {
|
|---|
| 6 | Node * parent;
|
|---|
| 7 | int data;
|
|---|
| 8 | // reference counter. A Node object can be deleted iff its
|
|---|
| 9 | // ref_count == 0 :
|
|---|
| 10 | int ref_count;
|
|---|
| 11 | // number of ancesters. Node.num_ancest == Node.parent->num_ancest + 1
|
|---|
| 12 | int num_ancest;
|
|---|
| 13 | };
|
|---|
| 14 |
|
|---|
| 15 | struct Tree {
|
|---|
| 16 | int history;
|
|---|
| 17 | Node * xs; // reference to the last added node
|
|---|
| 18 | Node * ys; // caterpillar
|
|---|
| 19 | };
|
|---|
| 20 |
|
|---|
| 21 | /* ********** helper functions ********** */
|
|---|
| 22 | // garbage collection ...
|
|---|
| 23 | void gc(Node * node) {
|
|---|
| 24 | if (node == NULL || node->ref_count > 0)
|
|---|
| 25 | return;
|
|---|
| 26 |
|
|---|
| 27 | Node * next = node->parent;
|
|---|
| 28 |
|
|---|
| 29 | free(node);
|
|---|
| 30 | if (next != NULL) {
|
|---|
| 31 | next->ref_count--;
|
|---|
| 32 | gc(next);
|
|---|
| 33 | }
|
|---|
| 34 | }
|
|---|
| 35 |
|
|---|
| 36 | /* ********** functions implements interfaces ********** */
|
|---|
| 37 | Node * make_node(int data) {
|
|---|
| 38 | Node * node = (Node*)malloc(sizeof(Node));
|
|---|
| 39 |
|
|---|
| 40 | node->parent = NULL;
|
|---|
| 41 | node->data = data;
|
|---|
| 42 | node->ref_count = 0;
|
|---|
| 43 | node->num_ancest = 0;
|
|---|
| 44 | return node;
|
|---|
| 45 | }
|
|---|
| 46 |
|
|---|
| 47 | int get_data(Node * node) {
|
|---|
| 48 | $assert(node, "attempt to get data from a invalid node reference");
|
|---|
| 49 | return node->data;
|
|---|
| 50 | }
|
|---|
| 51 |
|
|---|
| 52 | Tree * empty(int history) {
|
|---|
| 53 | Tree * tree = (Tree*)malloc(sizeof(Tree));
|
|---|
| 54 |
|
|---|
| 55 | tree->history = history;
|
|---|
| 56 | tree->xs = NULL;
|
|---|
| 57 | tree->ys = NULL;
|
|---|
| 58 | return tree;
|
|---|
| 59 | }
|
|---|
| 60 |
|
|---|
| 61 | Tree * add(Tree * tree, int data) {
|
|---|
| 62 | Node * node = make_node(data);
|
|---|
| 63 | Tree * new_tree = empty(tree->history);
|
|---|
| 64 |
|
|---|
| 65 | if (tree->xs == NULL) {
|
|---|
| 66 | new_tree->xs = node;
|
|---|
| 67 | new_tree->xs->ref_count++;
|
|---|
| 68 | new_tree->ys = tree->ys;
|
|---|
| 69 | if (tree->ys!=NULL)
|
|---|
| 70 | tree->ys->ref_count++;
|
|---|
| 71 | } else if(tree->xs->num_ancest < tree->history - 2) {
|
|---|
| 72 | node->parent = tree->xs;
|
|---|
| 73 | node->parent->ref_count++;
|
|---|
| 74 | node->num_ancest = node->parent->num_ancest + 1;
|
|---|
| 75 | new_tree->xs = node;
|
|---|
| 76 | new_tree->xs->ref_count++;
|
|---|
| 77 | new_tree->ys = tree->ys;
|
|---|
| 78 | if (tree->ys != NULL)
|
|---|
| 79 | new_tree->ys->ref_count++;
|
|---|
| 80 | } else {
|
|---|
| 81 | node->parent = tree->xs;
|
|---|
| 82 | node->parent->ref_count++;
|
|---|
| 83 | node->num_ancest = node->parent->num_ancest + 1;
|
|---|
| 84 | new_tree->ys = node;
|
|---|
| 85 | new_tree->ys->ref_count++;
|
|---|
| 86 | }
|
|---|
| 87 | return new_tree;
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | // Note: "ancestors" is an 0-terminated array:
|
|---|
| 91 | void take(Tree * tree, Node * ancestors[]) {
|
|---|
| 92 | int history = tree->history;
|
|---|
| 93 | int i = 0;
|
|---|
| 94 | Node * ancestor = tree->xs;
|
|---|
| 95 |
|
|---|
| 96 | while (i < history && ancestor != NULL) {
|
|---|
| 97 | ancestors[i++] = ancestor;
|
|---|
| 98 | ancestor = ancestor->parent;
|
|---|
| 99 | }
|
|---|
| 100 | ancestor = tree->ys;
|
|---|
| 101 | while (i < history && ancestor != NULL) {
|
|---|
| 102 | ancestors[i++] = ancestor;
|
|---|
| 103 | ancestor = ancestor->parent;
|
|---|
| 104 | }
|
|---|
| 105 | ancestors[i] = 0;
|
|---|
| 106 | }
|
|---|
| 107 |
|
|---|
| 108 | void delete(Tree * tree) {
|
|---|
| 109 | // took ys off and garbage collection:
|
|---|
| 110 | if (tree->ys != NULL) {
|
|---|
| 111 | Node * ys = tree->ys;
|
|---|
| 112 |
|
|---|
| 113 | tree->ys = NULL;
|
|---|
| 114 | ys->ref_count--;
|
|---|
| 115 | gc(ys);
|
|---|
| 116 | }
|
|---|
| 117 | if (tree->xs != NULL) {
|
|---|
| 118 | Node * xs = tree->xs;
|
|---|
| 119 |
|
|---|
| 120 | tree->xs = NULL;
|
|---|
| 121 | xs->ref_count--;
|
|---|
| 122 | gc(xs);
|
|---|
| 123 | }
|
|---|
| 124 | free(tree);
|
|---|
| 125 | }
|
|---|
| 126 |
|
|---|
| 127 |
|
|---|