modules/up/src/gnug++/CacheKey.CacheValue.AVLMap.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- bf
- set_bf
- rthread
- set_rthread
- lthread
- set_lthread
- leftmost
- rightmost
- succ
- pred
- seek
- _add
- _del
- del
- _kill
- CacheKeyCacheValueAVLMap
- OK
1 // This may look like C code, but it is really -*- C++ -*-
2 /*
3 Copyright (C) 1988 Free Software Foundation
4 written by Doug Lea (dl@rocky.oswego.edu)
5
6 This file is part of the GNU C++ Library. This library is free
7 software; you can redistribute it and/or modify it under the terms of
8 the GNU Library General Public License as published by the Free
9 Software Foundation; either version 2 of the License, or (at your
10 option) any later version. This library is distributed in the hope
11 that it will be useful, but WITHOUT ANY WARRANTY; without even the
12 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 PURPOSE. See the GNU Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #ifdef __GNUG__
20 #pragma implementation
21 #endif
22 #include "CacheKey.CacheValue.AVLMap.h"
23
24
25 /*
26 constants & inlines for maintaining balance & thread status in tree nodes
27 */
28
29 #define AVLBALANCEMASK 3
30 #define AVLBALANCED 0
31 #define AVLLEFTHEAVY 1
32 #define AVLRIGHTHEAVY 2
33
34 #define LTHREADBIT 4
35 #define RTHREADBIT 8
36
37
38 static inline int bf(CacheKeyCacheValueAVLNode* t)
/* [<][>][^][v][top][bottom][index][help] */
39 {
40 return t->stat & AVLBALANCEMASK;
41 }
42
43 static inline void set_bf(CacheKeyCacheValueAVLNode* t, int b)
/* [<][>][^][v][top][bottom][index][help] */
44 {
45 t->stat = (t->stat & ~AVLBALANCEMASK) | (b & AVLBALANCEMASK);
46 }
47
48
49 static inline int rthread(CacheKeyCacheValueAVLNode* t)
/* [<][>][^][v][top][bottom][index][help] */
50 {
51 return t->stat & RTHREADBIT;
52 }
53
54 static inline void set_rthread(CacheKeyCacheValueAVLNode* t, int b)
/* [<][>][^][v][top][bottom][index][help] */
55 {
56 if (b)
57 t->stat |= RTHREADBIT;
58 else
59 t->stat &= ~RTHREADBIT;
60 }
61
62 static inline int lthread(CacheKeyCacheValueAVLNode* t)
/* [<][>][^][v][top][bottom][index][help] */
63 {
64 return t->stat & LTHREADBIT;
65 }
66
67 static inline void set_lthread(CacheKeyCacheValueAVLNode* t, int b)
/* [<][>][^][v][top][bottom][index][help] */
68 {
69 if (b)
70 t->stat |= LTHREADBIT;
71 else
72 t->stat &= ~LTHREADBIT;
73 }
74
75 /*
76 traversal primitives
77 */
78
79
80 CacheKeyCacheValueAVLNode* CacheKeyCacheValueAVLMap::leftmost()
/* [<][>][^][v][top][bottom][index][help] */
81 {
82 CacheKeyCacheValueAVLNode* t = root;
83 if (t != 0) while (t->lt != 0) t = t->lt;
84 return t;
85 }
86
87 CacheKeyCacheValueAVLNode* CacheKeyCacheValueAVLMap::rightmost()
/* [<][>][^][v][top][bottom][index][help] */
88 {
89 CacheKeyCacheValueAVLNode* t = root;
90 if (t != 0) while (t->rt != 0) t = t->rt;
91 return t;
92 }
93
94 CacheKeyCacheValueAVLNode* CacheKeyCacheValueAVLMap::succ(CacheKeyCacheValueAVLNode* t)
/* [<][>][^][v][top][bottom][index][help] */
95 {
96 CacheKeyCacheValueAVLNode* r = t->rt;
97 if (!rthread(t)) while (!lthread(r)) r = r->lt;
98 return r;
99 }
100
101 CacheKeyCacheValueAVLNode* CacheKeyCacheValueAVLMap::pred(CacheKeyCacheValueAVLNode* t)
/* [<][>][^][v][top][bottom][index][help] */
102 {
103 CacheKeyCacheValueAVLNode* l = t->lt;
104 if (!lthread(t)) while (!rthread(l)) l = l->rt;
105 return l;
106 }
107
108
109 Pix CacheKeyCacheValueAVLMap::seek(CacheKey key)
/* [<][>][^][v][top][bottom][index][help] */
110 {
111 CacheKeyCacheValueAVLNode* t = root;
112 if (t == 0)
113 return 0;
114 for (;;)
115 {
116 int cmp = CacheKeyCMP(key, t->item);
117 if (cmp == 0)
118 return Pix(t);
119 else if (cmp < 0)
120 {
121 if (lthread(t))
122 return 0;
123 else
124 t = t->lt;
125 }
126 else if (rthread(t))
127 return 0;
128 else
129 t = t->rt;
130 }
131 }
132
133
134 /*
135 The combination of threads and AVL bits make adding & deleting
136 interesting, but very awkward.
137
138 We use the following statics to avoid passing them around recursively
139 */
140
141 static int _need_rebalancing; // to send back balance info from rec. calls
142 static CacheKey* _target_item; // add/del_item target
143 static CacheKeyCacheValueAVLNode* _found_node; // returned added/deleted node
144 static int _already_found; // for deletion subcases
145
146
147 void CacheKeyCacheValueAVLMap:: _add(CacheKeyCacheValueAVLNode*& t)
/* [<][>][^][v][top][bottom][index][help] */
148 {
149 int cmp = CacheKeyCMP(*_target_item, t->item);
150 if (cmp == 0)
151 {
152 _found_node = t;
153 return;
154 }
155 else if (cmp < 0)
156 {
157 if (lthread(t))
158 {
159 ++count;
160 _found_node = new CacheKeyCacheValueAVLNode(*_target_item, def);
161 set_lthread(_found_node, 1);
162 set_rthread(_found_node, 1);
163 _found_node->lt = t->lt;
164 _found_node->rt = t;
165 t->lt = _found_node;
166 set_lthread(t, 0);
167 _need_rebalancing = 1;
168 }
169 else
170 _add(t->lt);
171 if (_need_rebalancing)
172 {
173 switch(bf(t))
174 {
175 case AVLRIGHTHEAVY:
176 set_bf(t, AVLBALANCED);
177 _need_rebalancing = 0;
178 return;
179 case AVLBALANCED:
180 set_bf(t, AVLLEFTHEAVY);
181 return;
182 case AVLLEFTHEAVY:
183 {
184 CacheKeyCacheValueAVLNode* l = t->lt;
185 if (bf(l) == AVLLEFTHEAVY)
186 {
187 if (rthread(l))
188 t->lt = l;
189 else
190 t->lt = l->rt;
191 set_lthread(t, rthread(l));
192 l->rt = t;
193 set_rthread(l, 0);
194 set_bf(t, AVLBALANCED);
195 set_bf(l, AVLBALANCED);
196 t = l;
197 _need_rebalancing = 0;
198 }
199 else
200 {
201 CacheKeyCacheValueAVLNode* r = l->rt;
202 set_rthread(l, lthread(r));
203 if (lthread(r))
204 l->rt = r;
205 else
206 l->rt = r->lt;
207 r->lt = l;
208 set_lthread(r, 0);
209 set_lthread(t, rthread(r));
210 if (rthread(r))
211 t->lt = r;
212 else
213 t->lt = r->rt;
214 r->rt = t;
215 set_rthread(r, 0);
216 if (bf(r) == AVLLEFTHEAVY)
217 set_bf(t, AVLRIGHTHEAVY);
218 else
219 set_bf(t, AVLBALANCED);
220 if (bf(r) == AVLRIGHTHEAVY)
221 set_bf(l, AVLLEFTHEAVY);
222 else
223 set_bf(l, AVLBALANCED);
224 set_bf(r, AVLBALANCED);
225 t = r;
226 _need_rebalancing = 0;
227 return;
228 }
229 }
230 }
231 }
232 }
233 else
234 {
235 if (rthread(t))
236 {
237 ++count;
238 _found_node = new CacheKeyCacheValueAVLNode(*_target_item, def);
239 set_rthread(t, 0);
240 set_lthread(_found_node, 1);
241 set_rthread(_found_node, 1);
242 _found_node->lt = t;
243 _found_node->rt = t->rt;
244 t->rt = _found_node;
245 _need_rebalancing = 1;
246 }
247 else
248 _add(t->rt);
249 if (_need_rebalancing)
250 {
251 switch(bf(t))
252 {
253 case AVLLEFTHEAVY:
254 set_bf(t, AVLBALANCED);
255 _need_rebalancing = 0;
256 return;
257 case AVLBALANCED:
258 set_bf(t, AVLRIGHTHEAVY);
259 return;
260 case AVLRIGHTHEAVY:
261 {
262 CacheKeyCacheValueAVLNode* r = t->rt;
263 if (bf(r) == AVLRIGHTHEAVY)
264 {
265 if (lthread(r))
266 t->rt = r;
267 else
268 t->rt = r->lt;
269 set_rthread(t, lthread(r));
270 r->lt = t;
271 set_lthread(r, 0);
272 set_bf(t, AVLBALANCED);
273 set_bf(r, AVLBALANCED);
274 t = r;
275 _need_rebalancing = 0;
276 }
277 else
278 {
279 CacheKeyCacheValueAVLNode* l = r->lt;
280 set_lthread(r, rthread(l));
281 if (rthread(l))
282 r->lt = l;
283 else
284 r->lt = l->rt;
285 l->rt = r;
286 set_rthread(l, 0);
287 set_rthread(t, lthread(l));
288 if (lthread(l))
289 t->rt = l;
290 else
291 t->rt = l->lt;
292 l->lt = t;
293 set_lthread(l, 0);
294 if (bf(l) == AVLRIGHTHEAVY)
295 set_bf(t, AVLLEFTHEAVY);
296 else
297 set_bf(t, AVLBALANCED);
298 if (bf(l) == AVLLEFTHEAVY)
299 set_bf(r, AVLRIGHTHEAVY);
300 else
301 set_bf(r, AVLBALANCED);
302 set_bf(l, AVLBALANCED);
303 t = l;
304 _need_rebalancing = 0;
305 return;
306 }
307 }
308 }
309 }
310 }
311 }
312
313
314 CacheValue& CacheKeyCacheValueAVLMap::operator [] (CacheKey item)
315 {
316 if (root == 0)
317 {
318 ++count;
319 root = new CacheKeyCacheValueAVLNode(item, def);
320 set_rthread(root, 1);
321 set_lthread(root, 1);
322 return root->cont;
323 }
324 else
325 {
326 _target_item = &item;
327 _need_rebalancing = 0;
328 _add(root);
329 return _found_node->cont;
330 }
331 }
332
333
334 void CacheKeyCacheValueAVLMap::_del(CacheKeyCacheValueAVLNode* par, CacheKeyCacheValueAVLNode*& t)
/* [<][>][^][v][top][bottom][index][help] */
335 {
336 int comp;
337 if (_already_found)
338 {
339 if (rthread(t))
340 comp = 0;
341 else
342 comp = 1;
343 }
344 else
345 comp = CacheKeyCMP(*_target_item, t->item);
346 if (comp == 0)
347 {
348 if (lthread(t) && rthread(t))
349 {
350 _found_node = t;
351 if (t == par->lt)
352 {
353 set_lthread(par, 1);
354 par->lt = t->lt;
355 }
356 else
357 {
358 set_rthread(par, 1);
359 par->rt = t->rt;
360 }
361 _need_rebalancing = 1;
362 return;
363 }
364 else if (lthread(t))
365 {
366 _found_node = t;
367 CacheKeyCacheValueAVLNode* s = succ(t);
368 if (s != 0 && lthread(s))
369 s->lt = t->lt;
370 t = t->rt;
371 _need_rebalancing = 1;
372 return;
373 }
374 else if (rthread(t))
375 {
376 _found_node = t;
377 CacheKeyCacheValueAVLNode* p = pred(t);
378 if (p != 0 && rthread(p))
379 p->rt = t->rt;
380 t = t->lt;
381 _need_rebalancing = 1;
382 return;
383 }
384 else // replace item & find someone deletable
385 {
386 CacheKeyCacheValueAVLNode* p = pred(t);
387 t->item = p->item;
388 t->cont = p->cont;
389 _already_found = 1;
390 comp = -1; // fall through below to left
391 }
392 }
393
394 if (comp < 0)
395 {
396 if (lthread(t))
397 return;
398 _del(t, t->lt);
399 if (!_need_rebalancing)
400 return;
401 switch (bf(t))
402 {
403 case AVLLEFTHEAVY:
404 set_bf(t, AVLBALANCED);
405 return;
406 case AVLBALANCED:
407 set_bf(t, AVLRIGHTHEAVY);
408 _need_rebalancing = 0;
409 return;
410 case AVLRIGHTHEAVY:
411 {
412 CacheKeyCacheValueAVLNode* r = t->rt;
413 switch (bf(r))
414 {
415 case AVLBALANCED:
416 if (lthread(r))
417 t->rt = r;
418 else
419 t->rt = r->lt;
420 set_rthread(t, lthread(r));
421 r->lt = t;
422 set_lthread(r, 0);
423 set_bf(t, AVLRIGHTHEAVY);
424 set_bf(r, AVLLEFTHEAVY);
425 _need_rebalancing = 0;
426 t = r;
427 return;
428 case AVLRIGHTHEAVY:
429 if (lthread(r))
430 t->rt = r;
431 else
432 t->rt = r->lt;
433 set_rthread(t, lthread(r));
434 r->lt = t;
435 set_lthread(r, 0);
436 set_bf(t, AVLBALANCED);
437 set_bf(r, AVLBALANCED);
438 t = r;
439 return;
440 case AVLLEFTHEAVY:
441 {
442 CacheKeyCacheValueAVLNode* l = r->lt;
443 set_lthread(r, rthread(l));
444 if (rthread(l))
445 r->lt = l;
446 else
447 r->lt = l->rt;
448 l->rt = r;
449 set_rthread(l, 0);
450 set_rthread(t, lthread(l));
451 if (lthread(l))
452 t->rt = l;
453 else
454 t->rt = l->lt;
455 l->lt = t;
456 set_lthread(l, 0);
457 if (bf(l) == AVLRIGHTHEAVY)
458 set_bf(t, AVLLEFTHEAVY);
459 else
460 set_bf(t, AVLBALANCED);
461 if (bf(l) == AVLLEFTHEAVY)
462 set_bf(r, AVLRIGHTHEAVY);
463 else
464 set_bf(r, AVLBALANCED);
465 set_bf(l, AVLBALANCED);
466 t = l;
467 return;
468 }
469 }
470 }
471 }
472 }
473 else
474 {
475 if (rthread(t))
476 return;
477 _del(t, t->rt);
478 if (!_need_rebalancing)
479 return;
480 switch (bf(t))
481 {
482 case AVLRIGHTHEAVY:
483 set_bf(t, AVLBALANCED);
484 return;
485 case AVLBALANCED:
486 set_bf(t, AVLLEFTHEAVY);
487 _need_rebalancing = 0;
488 return;
489 case AVLLEFTHEAVY:
490 {
491 CacheKeyCacheValueAVLNode* l = t->lt;
492 switch (bf(l))
493 {
494 case AVLBALANCED:
495 if (rthread(l))
496 t->lt = l;
497 else
498 t->lt = l->rt;
499 set_lthread(t, rthread(l));
500 l->rt = t;
501 set_rthread(l, 0);
502 set_bf(t, AVLLEFTHEAVY);
503 set_bf(l, AVLRIGHTHEAVY);
504 _need_rebalancing = 0;
505 t = l;
506 return;
507 case AVLLEFTHEAVY:
508 if (rthread(l))
509 t->lt = l;
510 else
511 t->lt = l->rt;
512 set_lthread(t, rthread(l));
513 l->rt = t;
514 set_rthread(l, 0);
515 set_bf(t, AVLBALANCED);
516 set_bf(l, AVLBALANCED);
517 t = l;
518 return;
519 case AVLRIGHTHEAVY:
520 {
521 CacheKeyCacheValueAVLNode* r = l->rt;
522 set_rthread(l, lthread(r));
523 if (lthread(r))
524 l->rt = r;
525 else
526 l->rt = r->lt;
527 r->lt = l;
528 set_lthread(r, 0);
529 set_lthread(t, rthread(r));
530 if (rthread(r))
531 t->lt = r;
532 else
533 t->lt = r->rt;
534 r->rt = t;
535 set_rthread(r, 0);
536 if (bf(r) == AVLLEFTHEAVY)
537 set_bf(t, AVLRIGHTHEAVY);
538 else
539 set_bf(t, AVLBALANCED);
540 if (bf(r) == AVLRIGHTHEAVY)
541 set_bf(l, AVLLEFTHEAVY);
542 else
543 set_bf(l, AVLBALANCED);
544 set_bf(r, AVLBALANCED);
545 t = r;
546 return;
547 }
548 }
549 }
550 }
551 }
552 }
553
554
555
556 void CacheKeyCacheValueAVLMap::del(CacheKey item)
/* [<][>][^][v][top][bottom][index][help] */
557 {
558 if (root == 0) return;
559 _need_rebalancing = 0;
560 _already_found = 0;
561 _found_node = 0;
562 _target_item = &item;
563 _del(root, root);
564 if (_found_node)
565 {
566 delete(_found_node);
567 if (--count == 0)
568 root = 0;
569 }
570 }
571
572 void CacheKeyCacheValueAVLMap::_kill(CacheKeyCacheValueAVLNode* t)
/* [<][>][^][v][top][bottom][index][help] */
573 {
574 if (t != 0)
575 {
576 if (!lthread(t)) _kill(t->lt);
577 if (!rthread(t)) _kill(t->rt);
578 delete t;
579 }
580 }
581
582
583 CacheKeyCacheValueAVLMap::CacheKeyCacheValueAVLMap(CacheKeyCacheValueAVLMap& b) :CacheKeyCacheValueMap(b.def)
/* [<][>][^][v][top][bottom][index][help] */
584 {
585 root = 0;
586 count = 0;
587 for (Pix i = b.first(); i != 0; b.next(i))
588 (*this)[b.key(i)] = b.contents(i);
589 }
590
591
592 int CacheKeyCacheValueAVLMap::OK()
/* [<][>][^][v][top][bottom][index][help] */
593 {
594 int v = 1;
595 if (root == 0)
596 v = count == 0;
597 else
598 {
599 int n = 1;
600 CacheKeyCacheValueAVLNode* trail = leftmost();
601 CacheKeyCacheValueAVLNode* t = succ(trail);
602 while (t != 0)
603 {
604 ++n;
605 v &= CacheKeyCMP(trail->item, t->item) < 0;
606 trail = t;
607 t = succ(t);
608 }
609 v &= n == count;
610 }
611 if (!v) error("invariant failure");
612 return v;
613 }