source: CIVL/examples/verifyThis/treeBuffer/treebuffer.cvl@ 7d77e64

main test-branch
Last change on this file since 7d77e64 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100755
File size: 10.9 KB
RevLine 
[a999c3f]1#include <stdio.h>
2#include <seq.cvh>
3#include <assert.h>
4#include <stdarg.h>
5#include <stdint.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include "treebuffer.h"
9
10#define unused(x) ((void)x)
11#define M (t->mems += 1)
12#define MM (t->mems += 2)
13#define MMM (t->mems += 3)
14#define MMMM (t->mems += 4)
15
16struct Node {
17 Node * parent;
18 int children; // the number of x such that (x->parent == this)
19 Node * ll, * rl; // left link, right link; used for several lists
20 int depth; // distance to root
21 Node * representant; // ancestor with (depth % history == 0)
22 int active_count; // number of x that are active and x->representant == this
23 char seen; // used for garbage collection
24 char active;
25 int data;
26
27 // NOTE: All lists using |ll| and |rl| are doubly linked, circular, and
28 // using a sentinel.
29
30 // TODO: pointer to tree so that I can assert that added nodes aren't already in a tree
31};
32
33typedef struct TBTree {
34 int history;
35 enum algo algo;
36 Node * active; // list of active nodes
37 Node * to_delete;
38 // FILE * statistics_file;
39 int node_count; // only maintained by tb_amortized
40 int last_gc_node_count; // only maintained by tb_amortized
41 int mems;
42 int ref_count; // references from "Tree"
43} TBTree;
44
45struct Tree {
46 int history;
47 TBTree * tree;
48 Node * last_add;
49};
50
51Node * tb_make_node(int data) {
52 Node * r = malloc(sizeof(Node));
53 r->parent = 0;
54 r->children = 0;
55 r->ll = r->rl = r;
56 r->depth = -1;
57 r->representant = 0;
58 r->active_count = 0;
59 r->seen = 0;
60 r->active = 1;
61 r->data = data;
62 return r;
63}
64
65int tb_get_data(Node * x) {
66 return x->data;
67}
68
69TBTree * tb_initialize(int history, enum algo algo, Node * root) {
70 assert (root);
71 assert (history > 0);
72 TBTree * t = malloc(sizeof(TBTree));
73 t->history = history;
74 t->algo = algo;
75 t->active = malloc(sizeof(Node));
76 t->active->ll = t->active->rl = root;
77 t->active->parent = 0;
78 root->ll = root->rl = t->active;
79 root->depth = 0;
80 root->representant = root;
81 root->active_count = 1;
82 assert (root->active);
83 t->to_delete = malloc(sizeof(Node));
84 t->to_delete->ll = t->to_delete->rl = t->to_delete;
85 //t->statistics_file = 0;
86 t->node_count = 1;
87 t->last_gc_node_count = 1;
88 t->mems = 0;
89 t->ref_count = 0;
90 return t;
91}
92
93void cut_parent(TBTree * t, Node * y) {
94 Node * x = (M, y->parent);
95 if (x && (M, --x->children == 0) && !(M, x->active)) {
96 assert (x->ll == x); // not in some other list
97 assert (x->rl == x);
98 x->ll = t->to_delete, MM; x->rl = t->to_delete->rl, MMM;
99 x->ll->rl = x->rl->ll = x, MMMM;
100 }
101 y->parent = 0, M;
102}
103
104void delete_one(TBTree * t) {
105 assert (t);
106 Node * x = (MM, t->to_delete->rl);
107 if ((M, x == t->to_delete)) return;
108 assert (t->algo == tb_real_time);
109 x->ll->rl = x->rl, MMM; x->rl->ll = x->ll, MMM;
110 x->ll = x->rl = x, MM;
111 cut_parent(t, x);
112 free(x), M;
113}
114
115void tb_delete(TBTree * t) {
116 if (!t) return;
117 assert (t->mems == 0);
118
119 // Move |active| into |to_delete|.
120 { Node * L = (MM, t->active->ll);
121 Node * R = (MM, t->active->rl);
122 R->ll = t->to_delete, MM;
123 L->rl = t->to_delete->rl, MMM;
124 t->active->rl->ll->rl = t->active->rl; t->mems += 6;
125 t->active->ll->rl->ll = t->active->ll; t->mems += 6;
126 t->active->ll = t->active->rl = t->active; t->mems += 5;
127 }
128
129 // Cleanup.
130 t->algo = tb_real_time, M;
131 while ((MMM, t->to_delete->rl != t->to_delete)) delete_one(t);
132 t->mems = 0;
133 free(t->active);
134 free(t->to_delete);
135 free(t);
136}
137
138void gc_todo_parent(TBTree * t, Node * y, Node * todo) {
139 assert (y);
140 Node * x = (M, y->parent);
141 if (!x) return;
142 if ((M, x->seen)) return;
143 x->seen = 1, M;
144 x->ll = todo, M; x->rl = todo->rl, MM;
145 x->ll->rl = x->rl->ll = x, MMMM;
146}
147
148void gc_parent(TBTree *, Node *);
149
150void gc_node(TBTree * t, Node * x) {
151 assert (t);
152 assert (x);
153 assert (!x->seen);
154 assert (!x->active);
155 assert (x->children == 0);
156 gc_parent(t, x);
157 free(x);
158 if (t->algo == tb_amortized) --t->node_count, M;
159}
160
161void gc_parent(TBTree * t, Node * y) {
162 assert (t);
163 assert (y);
164 Node * x = (M, y->parent);
165 y->parent = 0, M;
166 if (x && (M, --x->children == 0) && (M, !x->seen)) {
167 gc_node(t, x);
168 }
169}
170
171void gc(TBTree * t) {
172 assert (t);
173 assert (t->algo == tb_gc || t->algo == tb_amortized);
174
175 for (Node * n = (MM, t->active->rl); (M, n != t->active); (M, n = n->rl)) {
176 n->seen = 1, M;
177 }
178 Node sentinel_a, sentinel_b, sentinel_c;
179 Node * now; // being processed now
180 Node * todo; // to process after now
181 Node * middle; // was processed, but doesn't include active nodes
182 now = &sentinel_a; todo = &sentinel_b; middle = &sentinel_c;
183 middle->ll = middle->rl = middle, MM;
184 now->ll = now->rl = now, MM;
185 todo->ll = todo->rl = todo, MM;
186 for (Node * n = (MM, t->active->rl); (M, n != t->active); (M, n = n->rl)) {
187 gc_todo_parent(t, n, todo);
188 }
189 for (int layer = 2; (MM, layer < t->history && todo != todo->rl); ++layer) {
190 { Node * tmp = now; now = todo; todo = tmp; }
191 for (Node * n = (M, now->rl); n != now; (M, n = n->rl)) {
192 gc_todo_parent(t, n, todo);
193 }
194
195 // Move |now| content into |middle|.
196 { Node * nl = (M, now->ll);
197 Node * nr = (M, now->rl);
198 nr->ll = middle, M;
199 nl->rl = middle->rl, MM;
200 now->rl->ll->rl = now->rl, MMMM;
201 now->ll->rl->ll = now->ll, MMMM;
202 now->ll = now->rl = now, MM;
203 }
204 }
205 for (Node * n = (M, todo->rl); n != todo; (M, n = n->rl)) {
206 gc_parent(t, n);
207 }
208 { Node * p, * q;
209 for (p = (MM, t->to_delete->rl); p != (M, t->to_delete); p = q) {
210 q = p->rl, M;
211 gc_node(t, p);
212 }
213 t->to_delete->rl = t->to_delete->ll = t->to_delete, t->mems += 5;
214 }
215 assert (now->ll == now);
216 assert (now->rl == now);
217 for (Node * n = (M, todo->rl); n != todo; (M, n = n->rl)) n->seen = 0, M;
218 for (Node * n = (M, middle->rl); n != middle; (M, n = n->rl)) n->seen = 0, M;
219 for (Node * n = (MM, t->active->rl); (M, n != t->active); (M, n = n->rl))
220 n->seen = 0, M;
221 { Node * p, * q;
222 for (p = (M, todo->rl); p != todo; p = q) {
223 q = p->rl, M;
224 p->ll = p->rl = p, MM;
225 }
226 for (p = (M, middle->rl); p != middle; p = q) {
227 q = p->rl, M;
228 p->ll = p->rl = p, MM;
229 }
230 }
231
232 if (t->algo == tb_amortized) {
233 t->last_gc_node_count = t->node_count, MM;
234 }
235}
236
237void tb_add_child(TBTree * t, Node * parent, Node * child) {
238 assert (t);
239 assert (t->mems == 0);
240 assert (parent);
241 assert (child);
242 child->parent = parent, M;
243 ++parent->children, M;
244 child->ll = t->active, MM; child->rl = t->active->rl, MMM;
245 child->ll->rl = child->rl->ll = child, MMMM;
246 if (t->algo == tb_amortized) {
247 if ((MM, ++t->node_count >= 2 * t->last_gc_node_count)) gc(t);
248 } else if (t->algo == tb_real_time) {
249 delete_one(t);
250 child->depth = parent->depth + 1, MM;
251 child->representant =
252 (MM, child->depth % t->history == 0)? child : (M, parent->representant); M;
253 ++child->representant->active_count, MM;
254 }
255 t->mems = 0;
256}
257
258void tb_deactivate(TBTree * t, Node * n) {
259 assert (t);
260 assert (t->mems == 0);
261 assert (n);
262 assert (n->active);
263 n->active = 0;
264 n->ll->rl = n->rl, MMM; n->rl->ll = n->ll, MMM;
265 n->ll = n->rl = n, MM;
266 if ((M, n->children == 0)) {
267 n->ll = t->to_delete, MM; n->rl = t->to_delete->rl, MMM;
268 n->ll->rl = n->rl->ll = n, MMMM;
269 }
270 if (t->algo == tb_gc) {
271 gc(t);
272 }
273 if (t->algo == tb_real_time) {
274 assert (n->representant);
275 if ((MM, --n->representant->active_count) == 0) {
276 cut_parent(t, n->representant);
277 }
278 }
279 t->mems = 0;
280}
281
282void tb_expand(TBTree * t, Node * parent, Node * children[]) {
283 for (Node ** n = children; *n; ++n) tb_add_child(t, parent, *n);
284 tb_deactivate(t, parent);
285}
286
287void tb_history(TBTree * t, Node * node, Node * ancestors[]) {
288 assert (t->mems == 0);
289 assert (node->active);
290 int h = (M, t->history);
291 while (node && h--) {
292 *ancestors++ = node, M;
293 node = node->parent, M;
294 }
295 *ancestors = 0, M;
296 t->mems = 0;
297}
298
299Node * tb_active(const TBTree * t) {
300 assert (t);
301 if (t->active->rl == t->active) return 0;
302 return t->active->rl;
303}
304
305// PRE: |n| is in |t| (*not* checked by assertions), and active
306Node * tb_next_active(const TBTree * t, const Node * n) {
307 assert (t);
308 assert (n);
309 // assert (n->active);
310 if (n->rl == t->active) return 0;
311 return n->rl;
312}
313
314/* ********* VerifyThis 2017 interface extension ********* */
315
316int get_data(Node * node) {
317 return tb_get_data(node);
318}
319
320Tree * empty(int history) {
321 Tree * tree = (Tree*)malloc(sizeof(Tree));
322
323 tree->history = history;
324 tree->tree = NULL;
325 tree->last_add = NULL;
326 return tree;
327}
328
329Tree * add(Tree * tree, int data) {
330 Node * child = tb_make_node(data);
331 Tree * new_tree = (Tree*)malloc(sizeof(Tree));
332
333 if (tree->tree == NULL) {
334 new_tree->tree = tb_initialize(tree->history, tb_real_time, child);
335 new_tree->history = tree->history;
336 new_tree->last_add = child;
337 } else {
338 tb_add_child(tree->tree, tree->last_add, child);
339 new_tree->tree = tree->tree;
340 new_tree->history = tree->history;
341 new_tree->last_add = child;
342 }
343 new_tree->tree->ref_count++;
344 return new_tree;
345}
346
347void take(Tree * tree, Node * ancestors[]) {
348 if (tree->tree != NULL)
349 tb_history(tree->tree, tree->last_add, ancestors);
350 else
351 ancestors[0] = 0;
352}
353
354void delete(Tree *tree) {
355 TBTree * tb_tree = tree->tree;
356
357 if (tb_tree!=NULL && --tb_tree->ref_count == 0)
358 tb_delete(tree->tree);
359 free(tree);
360}
361
362int hasSeen(Node * node, Node * seens[], int n) {
363 for (int i = 0; i < n; i++) {
364 if (node == seens[i]) return 1;
365 }
366 return 0;
367}
368
369/* Computing the H_<h, which is descried as the bound of the heap
370 size */
371int computing_bounds(Tree * tree) {
[0c90cbf]372 $atomic{
[a999c3f]373 TBTree * t = tree->tree;
374 Node *active = t->active;
375 Node * level[];
376 Node * seen[];
377
378 $seq_init(&level, 0, NULL);
379 $seq_init(&seen, 0, NULL);
380 while (active != NULL) {
381 $seq_append(&level, &active, 1);
382 $seq_append(&seen, &active, 1);
383 active = tb_next_active(t, active);
384 }
385
386 int i = 1;
387
388 while (i < tree->history) {
389 int level_size = $seq_length(&level);
390 int seen_size;
391 Node * nxt_level[];
392
393 $seq_init(&nxt_level, 0, NULL);
394 for (int j = 0; j < level_size; j++) {
395 active = level[j]->parent;
396 seen_size = $seq_length(&seen);
397 if (active != NULL)
398 if (!hasSeen(active, seen, seen_size)) {
399 $seq_append(&nxt_level, &active, 1);
400 $seq_append(&seen, &active, 1);
401 }
402 }
403 // level := nxt_levl ...
404 $seq_remove(&level, 0, NULL, level_size);
405 $seq_append(&level, &nxt_level, $seq_length(&nxt_level));
406 i++;
407 }
408 return $seq_length(&seen);
409 }
410}
411
412void check_heap_inbound(size_t heapsize, int history, Tree * tree, size_t *max) {
413 int H = computing_bounds(tree);
414 size_t boundsize = sizeof(Tree) + sizeof(TBTree) + sizeof(Node) * H
415 // root, active and to_delete ...
416 + sizeof(Node) * 3;
417
418 if (boundsize < *max)
419 boundsize = *max;
420 else
421 *max = boundsize;
422 printf("max=%d\n", *max);
423 printf("H<i=%d\n", H);
424 printf("heap_size=%d\n", heapsize);
425 printf("bound_size=%d\n", boundsize);
426 assert(boundsize >= heapsize);
427}
428
Note: See TracBrowser for help on using the repository browser.