if (! b->overlays)
return;
- /* FIXME: This loop sets the overlays' `buffer` field to NULL but
- doesn't set the itree_nodes' `parent`, `left` and `right`
- fields accordingly. I believe it's harmless, but a bit untidy since
- other parts of the code are careful to set those fields to NULL when
- the overlay is deleted.
- Of course, we can't set them to NULL from within the iteration
- because the iterator may need them (tho we could if we added
- an ITREE_POST_ORDER iteration order). */
- ITREE_FOREACH (node, b->overlays, PTRDIFF_MIN, PTRDIFF_MAX, ASCENDING)
+ /* The general rule is that the tree cannot be modified from within
+ ITREE_FOREACH, but here we bend this rule a little because we know
+ that the POST_ORDER iterator will not need to look at `node` again. */
+ ITREE_FOREACH (node, b->overlays, PTRDIFF_MIN, PTRDIFF_MAX, POST_ORDER)
{
modify_overlay (b, node->begin, node->end);
- /* Where are the nodes freed ? --ap */
XOVERLAY (node->data)->buffer = NULL;
+ node->parent = NULL;
+ node->left = NULL;
+ node->right = NULL;
}
itree_clear (b->overlays);
}
itree_insert_node (struct itree_tree *tree, struct itree_node *node)
{
eassert (node && node->begin <= node->end);
- /* FIXME: The assertion below fails because `delete_all_overlays`
- doesn't set left/right/parent to NULL. */
- /* eassert (node->left == NULL && node->right == NULL
- && node->parent == NULL) */;
+ eassert (node->left == NULL && node->right == NULL
+ && node->parent == NULL);
eassert (check_tree (tree, true)); /* FIXME: Too expensive. */
struct itree_node *parent = NULL;
itree_iter_next_in_subtree (struct itree_node *node,
struct itree_iterator *iter)
{
+ /* FIXME: Like in the previous version of the iterator, we
+ prune based on `limit` only when moving to a left child,
+ but `limit` can also get smaller when moving to a right child
+ It's actually fairly common, so maybe it would be worthwhile
+ to prune a bit more aggressively here. */
struct itree_node *next;
switch (iter->order)
{
iter->end = end;
iter->otick = tree->otick;
iter->order = order;
+ /* Beware: the `node` field alwyas holds "the next" node to consider.
+ so it's always "one node ahead" of what the iterator loop sees.
+ In most respects this makes no difference, but we depend on this
+ detail in `delete_all_overlays` where this allows us to modify
+ the current node knowing that the iterator will not need it to
+ find the next. */
iter->node = itree_iterator_first_node (tree, iter);
return iter;
}