diff options
| author | Matt Armstrong | 2022-10-10 10:45:05 -0700 |
|---|---|---|
| committer | Matt Armstrong | 2022-10-10 19:37:51 -0700 |
| commit | da0387f0fe79f577fae6d5453c758f600e1ae495 (patch) | |
| tree | 12aad28099e8718644f7d831202df266306f92fd /src | |
| parent | a154259bfacf7f1406794a952e80a8197b9a83fb (diff) | |
| download | emacs-da0387f0fe79f577fae6d5453c758f600e1ae495.tar.gz emacs-da0387f0fe79f577fae6d5453c758f600e1ae495.zip | |
Stop reading and writing the itree_null.parent field entirely.
With this change all fields in the itree_null sentinel are read only.
This makes accessing itree_null thread safe in an obvious way.
Because it took two commits from two peole to get this right, I think
we can call this design fragile and difficult to reason about.
Another benefit of this commit is as preparation for removing sentinel
node completely, and just using NULL.
* src/itree.c (itree_null): Statically initialize itree_null.parent to
NULL. It is never accessed.
(null_is_sane): Assert parent == NULL.
(interval_tree_remove_fix): Remove unecessary assignments to parent
from node->parent. These were the last places itree_null.parent were
read.
(interval_tree_remove): Avoid an assignment to itree_null.parent
through min->right->parent.
(interval_tree_transplant): Avoid an assignment to itree_null.parent
through source->parent.
Diffstat (limited to 'src')
| -rw-r--r-- | src/itree.c | 20 |
1 files changed, 7 insertions, 13 deletions
diff --git a/src/itree.c b/src/itree.c index d9f9ec8cd67..9c5d8ce1426 100644 --- a/src/itree.c +++ b/src/itree.c | |||
| @@ -146,7 +146,7 @@ static void interval_tree_insert (struct interval_tree *, struct interval_node * | |||
| 146 | 146 | ||
| 147 | /* The sentinel node, the null node. */ | 147 | /* The sentinel node, the null node. */ |
| 148 | struct interval_node itree_null = { | 148 | struct interval_node itree_null = { |
| 149 | .parent = &itree_null, | 149 | .parent = NULL, /* never accessed */ |
| 150 | .left = &itree_null, | 150 | .left = &itree_null, |
| 151 | .right = &itree_null, | 151 | .right = &itree_null, |
| 152 | .begin = PTRDIFF_MIN, | 152 | .begin = PTRDIFF_MIN, |
| @@ -162,12 +162,8 @@ struct interval_node itree_null = { | |||
| 162 | static bool | 162 | static bool |
| 163 | null_is_sane (void) | 163 | null_is_sane (void) |
| 164 | { | 164 | { |
| 165 | /* The sentinel node has most of its fields read-only. | 165 | /* All sentinel node fields are read-only. */ |
| 166 | 166 | eassert (itree_null.parent == NULL); | |
| 167 | FIXME: PARENT is still read/write. It is written to | ||
| 168 | ininterval_tree_transplant, and later read. --matt | ||
| 169 | */ | ||
| 170 | /* eassert (itree_null.parent == &itree_null); */ | ||
| 171 | eassert (itree_null.left == &itree_null); | 167 | eassert (itree_null.left == &itree_null); |
| 172 | eassert (itree_null.right == &itree_null); | 168 | eassert (itree_null.right == &itree_null); |
| 173 | eassert (itree_null.begin == PTRDIFF_MIN); | 169 | eassert (itree_null.begin == PTRDIFF_MIN); |
| @@ -742,7 +738,6 @@ interval_tree_remove_fix (struct interval_tree *tree, | |||
| 742 | other->red = false; | 738 | other->red = false; |
| 743 | parent->red = true; | 739 | parent->red = true; |
| 744 | interval_tree_rotate_left (tree, parent); | 740 | interval_tree_rotate_left (tree, parent); |
| 745 | parent = node->parent; | ||
| 746 | other = parent->right; | 741 | other = parent->right; |
| 747 | } | 742 | } |
| 748 | 743 | ||
| @@ -761,7 +756,6 @@ interval_tree_remove_fix (struct interval_tree *tree, | |||
| 761 | other->left->red = false; | 756 | other->left->red = false; |
| 762 | other->red = true; | 757 | other->red = true; |
| 763 | interval_tree_rotate_right (tree, other); | 758 | interval_tree_rotate_right (tree, other); |
| 764 | parent = node->parent; | ||
| 765 | other = parent->right; | 759 | other = parent->right; |
| 766 | } | 760 | } |
| 767 | other->red = parent->red; /* 4.a */ | 761 | other->red = parent->red; /* 4.a */ |
| @@ -781,7 +775,6 @@ interval_tree_remove_fix (struct interval_tree *tree, | |||
| 781 | other->red = false; | 775 | other->red = false; |
| 782 | parent->red = true; | 776 | parent->red = true; |
| 783 | interval_tree_rotate_right (tree, parent); | 777 | interval_tree_rotate_right (tree, parent); |
| 784 | parent = node->parent; | ||
| 785 | other = parent->left; | 778 | other = parent->left; |
| 786 | } | 779 | } |
| 787 | 780 | ||
| @@ -800,7 +793,6 @@ interval_tree_remove_fix (struct interval_tree *tree, | |||
| 800 | other->right->red = false; | 793 | other->right->red = false; |
| 801 | other->red = true; | 794 | other->red = true; |
| 802 | interval_tree_rotate_left (tree, other); | 795 | interval_tree_rotate_left (tree, other); |
| 803 | parent = node->parent; | ||
| 804 | other = parent->left; | 796 | other = parent->left; |
| 805 | } | 797 | } |
| 806 | 798 | ||
| @@ -881,7 +873,8 @@ interval_tree_remove (struct interval_tree *tree, struct interval_node *node) | |||
| 881 | interval_tree_transplant (tree, min, node); | 873 | interval_tree_transplant (tree, min, node); |
| 882 | /* We set min->right->parent after `interval_tree_transplant` so | 874 | /* We set min->right->parent after `interval_tree_transplant` so |
| 883 | that calls to `itree_total_offset` don't get stuck in an inf-loop. */ | 875 | that calls to `itree_total_offset` don't get stuck in an inf-loop. */ |
| 884 | min->right->parent = min; | 876 | if (min->right != ITREE_NULL) |
| 877 | min->right->parent = min; | ||
| 885 | interval_tree_update_limit (min); | 878 | interval_tree_update_limit (min); |
| 886 | /* This call "belongs" with the first `interval_tree_transplant` | 879 | /* This call "belongs" with the first `interval_tree_transplant` |
| 887 | (of `min_right`, done earlier in the `if`) but we prefer to do it | 880 | (of `min_right`, done earlier in the `if`) but we prefer to do it |
| @@ -1508,7 +1501,8 @@ interval_tree_transplant (struct interval_tree *tree, struct interval_node *sour | |||
| 1508 | else | 1501 | else |
| 1509 | dest->parent->right = source; | 1502 | dest->parent->right = source; |
| 1510 | 1503 | ||
| 1511 | source->parent = dest->parent; | 1504 | if (source != ITREE_NULL) |
| 1505 | source->parent = dest->parent; | ||
| 1512 | } | 1506 | } |
| 1513 | 1507 | ||
| 1514 | 1508 | ||