aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2022-10-05 12:12:01 -0400
committerStefan Monnier2022-10-05 12:12:01 -0400
commitaa5a32ca2c07691f3f10b7ec0c423ade11479220 (patch)
tree2852c532076b86fb544e07ad0dedf5fe834246c6 /src
parent4f4327c0b0db7f908ae7153e5ddc802b9808dc2e (diff)
downloademacs-aa5a32ca2c07691f3f10b7ec0c423ade11479220.tar.gz
emacs-aa5a32ca2c07691f3f10b7ec0c423ade11479220.zip
itree.c: Clarify how the sentinel is used
* src/itree.c (null_is_sane): New function. (interval_tree_iter_start): Use it to make sure we haven't garbled null. (itree_init): Fully initialize `itree_null` here... (interval_tree_clear): ...instead of here. (interval_tree_propagate_limit): Remove special code that read NULL->parent. (interval_tree_remove): Do it explicitly before the call in those two places where it can happen.
Diffstat (limited to 'src')
-rw-r--r--src/itree.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/src/itree.c b/src/itree.c
index 58456fbc6ee..dcad848c216 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -114,6 +114,19 @@ static struct interval_generator* interval_generator_create (struct interval_tre
114/* The sentinel node, the null node. */ 114/* The sentinel node, the null node. */
115struct interval_node itree_null; 115struct interval_node itree_null;
116 116
117static inline bool
118null_is_sane (void)
119{
120 /* The sentinel node has most of its fields read-only, except for `parent`,
121 `left`, `right` which are write only. */
122 return itree_null.red == false
123 && itree_null.otick == 0
124 && itree_null.offset == 0
125 && itree_null.begin == PTRDIFF_MIN
126 && itree_null.end == PTRDIFF_MIN
127 && itree_null.limit == PTRDIFF_MIN;
128}
129
117/* +------------------------------------------------------------------------------------+ */ 130/* +------------------------------------------------------------------------------------+ */
118 131
119typedef uintptr_t nodeptr_and_flag; 132typedef uintptr_t nodeptr_and_flag;
@@ -149,7 +162,13 @@ static struct interval_generator *iter;
149static void 162static void
150itree_init (void) 163itree_init (void)
151{ 164{
152 itree_null.parent = itree_null.left = itree_null.right = ITREE_NULL; 165 struct interval_node *null = ITREE_NULL;
166 null->left = null->right = null->parent = null;
167 null->offset = null->otick = 0;
168 null->begin = PTRDIFF_MIN;
169 null->end = PTRDIFF_MIN;
170 null->limit = PTRDIFF_MIN; /* => max(x, null.limit) = x */
171 null->red = false;
153 iter = interval_generator_create (NULL); 172 iter = interval_generator_create (NULL);
154} 173}
155 174
@@ -310,6 +329,7 @@ interval_node_set_region (struct interval_tree *tree,
310 else if (end != node->end) 329 else if (end != node->end)
311 { 330 {
312 node->end = max (node->begin, end); 331 node->end = max (node->begin, end);
332 eassert (node != ITREE_NULL);
313 interval_tree_propagate_limit (node); 333 interval_tree_propagate_limit (node);
314 } 334 }
315} 335}
@@ -334,16 +354,7 @@ interval_tree_create (void)
334void 354void
335interval_tree_clear (struct interval_tree *tree) 355interval_tree_clear (struct interval_tree *tree)
336{ 356{
337 /* FIXME: Why is this done? */ 357 tree->root = ITREE_NULL;
338 struct interval_node *null = ITREE_NULL;
339 null->left = null->right = null->parent = null;
340 null->offset = null->otick = 0;
341 null->begin = PTRDIFF_MIN;
342 null->end = PTRDIFF_MIN;
343 null->limit = PTRDIFF_MIN; /* => max(x, null.limit) = x */
344 null->red = false;
345
346 tree->root = null;
347 tree->otick = 1; 358 tree->otick = 1;
348 tree->size = 0; 359 tree->size = 0;
349} 360}
@@ -461,7 +472,9 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
461 if (!node->red) 472 if (!node->red)
462 broken = subst; 473 broken = subst;
463 interval_tree_transplant (tree, subst, node); 474 interval_tree_transplant (tree, subst, node);
464 interval_tree_propagate_limit (subst); 475 interval_tree_propagate_limit
476 /* FIXME: null->parent is supposed to be write only! */
477 (subst == ITREE_NULL ? ITREE_NULL->parent : subst);
465 } 478 }
466 else 479 else
467 { 480 {
@@ -472,7 +485,12 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
472 broken = min->right; 485 broken = min->right;
473 eassert (min != ITREE_NULL); 486 eassert (min != ITREE_NULL);
474 if (min->parent == node) 487 if (min->parent == node)
475 min_right->parent = min; /* set parent, if min_right = null */ 488 {
489 if (min_right == ITREE_NULL)
490 ITREE_NULL->parent = min; /* set parent, if min_right = null */
491 else
492 eassert (min_right->parent == min);
493 }
476 else 494 else
477 { 495 {
478 interval_tree_transplant (tree, min->right, min); 496 interval_tree_transplant (tree, min->right, min);
@@ -484,7 +502,9 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node)
484 min->left = node->left; 502 min->left = node->left;
485 min->left->parent = min; 503 min->left->parent = min;
486 min->red = node->red; 504 min->red = node->red;
487 interval_tree_propagate_limit (min_right); 505 interval_tree_propagate_limit
506 /* FIXME: null->parent is supposed to be write only! */
507 (min_right == ITREE_NULL ? ITREE_NULL->parent : min_right);
488 interval_tree_propagate_limit (min); 508 interval_tree_propagate_limit (min);
489 } 509 }
490 510
@@ -523,6 +543,7 @@ interval_tree_iter_start (struct interval_tree *tree,
523 enum interval_tree_order order, 543 enum interval_tree_order order,
524 const char* file, int line) 544 const char* file, int line)
525{ 545{
546 eassert (null_is_sane ());
526 /* struct interval_generator *iter = tree->iter; */ 547 /* struct interval_generator *iter = tree->iter; */
527 if (iter->running) 548 if (iter->running)
528 { 549 {
@@ -625,6 +646,7 @@ interval_tree_insert_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t l
625 if (node->end > pos || (node->end == pos && node->rear_advance)) 646 if (node->end > pos || (node->end == pos && node->rear_advance))
626 { 647 {
627 node->end += length; 648 node->end += length;
649 eassert (node != ITREE_NULL);
628 interval_tree_propagate_limit (node); 650 interval_tree_propagate_limit (node);
629 } 651 }
630 } 652 }
@@ -689,6 +711,7 @@ interval_tree_delete_gap (struct interval_tree *tree, ptrdiff_t pos, ptrdiff_t l
689 if (node->end > pos) 711 if (node->end > pos)
690 { 712 {
691 node->end = max (pos , node->end - length); 713 node->end = max (pos , node->end - length);
714 eassert (node != ITREE_NULL);
692 interval_tree_propagate_limit (node); 715 interval_tree_propagate_limit (node);
693 } 716 }
694 } 717 }
@@ -876,8 +899,6 @@ static void
876interval_tree_propagate_limit (struct interval_node *node) 899interval_tree_propagate_limit (struct interval_node *node)
877{ 900{
878 if (node == ITREE_NULL) 901 if (node == ITREE_NULL)
879 node = node->parent;
880 if (node == ITREE_NULL)
881 return; 902 return;
882 903
883 while (1) { 904 while (1) {