emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/noverlay aa5a32ca2c: itree.c: Clarify how the sentinel is used


From: Stefan Monnier
Subject: feature/noverlay aa5a32ca2c: itree.c: Clarify how the sentinel is used
Date: Wed, 5 Oct 2022 12:12:13 -0400 (EDT)

branch: feature/noverlay
commit aa5a32ca2c07691f3f10b7ec0c423ade11479220
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    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.
---
 src/itree.c | 53 +++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 37 insertions(+), 16 deletions(-)

diff --git a/src/itree.c b/src/itree.c
index 58456fbc6e..dcad848c21 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -114,6 +114,19 @@ static struct interval_generator* 
interval_generator_create (struct interval_tre
 /* The sentinel node, the null node.  */
 struct interval_node itree_null;
 
+static inline bool
+null_is_sane (void)
+{
+  /* The sentinel node has most of its fields read-only, except for `parent`,
+     `left`, `right` which are write only. */
+  return itree_null.red == false
+         && itree_null.otick == 0
+         && itree_null.offset == 0
+         && itree_null.begin == PTRDIFF_MIN
+         && itree_null.end == PTRDIFF_MIN
+         && itree_null.limit == PTRDIFF_MIN;
+}
+
 /* 
+------------------------------------------------------------------------------------+
 */
 
 typedef uintptr_t nodeptr_and_flag;
@@ -149,7 +162,13 @@ static struct interval_generator *iter;
 static void
 itree_init (void)
 {
-  itree_null.parent = itree_null.left = itree_null.right = ITREE_NULL;
+  struct interval_node *null = ITREE_NULL;
+  null->left = null->right = null->parent = null;
+  null->offset = null->otick = 0;
+  null->begin = PTRDIFF_MIN;
+  null->end = PTRDIFF_MIN;
+  null->limit = PTRDIFF_MIN;     /* => max(x, null.limit) = x */
+  null->red = false;
   iter = interval_generator_create (NULL);
 }
 
@@ -310,6 +329,7 @@ interval_node_set_region (struct interval_tree *tree,
   else if (end != node->end)
     {
       node->end = max (node->begin, end);
+      eassert (node != ITREE_NULL);
       interval_tree_propagate_limit (node);
     }
 }
@@ -334,16 +354,7 @@ interval_tree_create (void)
 void
 interval_tree_clear (struct interval_tree *tree)
 {
-  /* FIXME: Why is this done?  */
-  struct interval_node *null = ITREE_NULL;
-  null->left = null->right = null->parent = null;
-  null->offset = null->otick = 0;
-  null->begin = PTRDIFF_MIN;
-  null->end = PTRDIFF_MIN;
-  null->limit = PTRDIFF_MIN;     /* => max(x, null.limit) = x */
-  null->red = false;
-
-  tree->root = null;
+  tree->root = ITREE_NULL;
   tree->otick = 1;
   tree->size = 0;
 }
@@ -461,7 +472,9 @@ interval_tree_remove (struct interval_tree *tree, struct 
interval_node *node)
       if (!node->red)
         broken = subst;
       interval_tree_transplant (tree, subst, node);
-      interval_tree_propagate_limit (subst);
+      interval_tree_propagate_limit
+        /* FIXME: null->parent is supposed to be write only!  */
+        (subst == ITREE_NULL ? ITREE_NULL->parent : subst);
     }
   else
     {
@@ -472,7 +485,12 @@ interval_tree_remove (struct interval_tree *tree, struct 
interval_node *node)
         broken = min->right;
       eassert (min != ITREE_NULL);
       if (min->parent == node)
-        min_right->parent = min; /* set parent, if min_right = null */
+        {
+          if (min_right == ITREE_NULL)
+            ITREE_NULL->parent = min; /* set parent, if min_right = null */
+          else
+            eassert (min_right->parent == min);
+        }
       else
         {
           interval_tree_transplant (tree, min->right, min);
@@ -484,7 +502,9 @@ interval_tree_remove (struct interval_tree *tree, struct 
interval_node *node)
       min->left = node->left;
       min->left->parent = min;
       min->red = node->red;
-      interval_tree_propagate_limit (min_right);
+      interval_tree_propagate_limit
+        /* FIXME: null->parent is supposed to be write only!  */
+        (min_right == ITREE_NULL ? ITREE_NULL->parent : min_right);
       interval_tree_propagate_limit (min);
     }
 
@@ -523,6 +543,7 @@ interval_tree_iter_start (struct interval_tree *tree,
                           enum interval_tree_order order,
                          const char* file, int line)
 {
+  eassert (null_is_sane ());
   /* struct interval_generator *iter = tree->iter; */
   if (iter->running)
     {
@@ -625,6 +646,7 @@ interval_tree_insert_gap (struct interval_tree *tree, 
ptrdiff_t pos, ptrdiff_t l
           if (node->end > pos || (node->end == pos && node->rear_advance))
             {
               node->end += length;
+              eassert (node != ITREE_NULL);
               interval_tree_propagate_limit (node);
             }
         }
@@ -689,6 +711,7 @@ interval_tree_delete_gap (struct interval_tree *tree, 
ptrdiff_t pos, ptrdiff_t l
       if (node->end > pos)
         {
           node->end = max (pos , node->end - length);
+          eassert (node != ITREE_NULL);
           interval_tree_propagate_limit (node);
         }
     }
@@ -875,8 +898,6 @@ interval_tree_inherit_offset (uintmax_t otick, struct 
interval_node *node)
 static void
 interval_tree_propagate_limit (struct interval_node *node)
 {
-  if (node == ITREE_NULL)
-    node = node->parent;
   if (node == ITREE_NULL)
     return;
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]