From: Stefan Monnier Date: Fri, 7 Oct 2022 23:15:07 +0000 (-0400) Subject: itree: Try and detect non-local exits during itree iterations X-Git-Tag: emacs-29.0.90~1616^2~406^2~29 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=208de5de59ae85887d637ec93690e17c418a7ab6;p=emacs.git itree: Try and detect non-local exits during itree iterations * src/itree.c (itree_busy_p): New function. * src/eval.c (signal_or_quit): Use it. * src/itree.h (itree_busy_p): Declare it. --- diff --git a/src/eval.c b/src/eval.c index 7da1d8fb989..37c25c79148 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1711,6 +1711,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) Lisp_Object clause = Qnil; struct handler *h; + eassert (!itree_busy_p ()); if (gc_in_progress || waiting_for_input) emacs_abort (); diff --git a/src/itree.c b/src/itree.c index d955c575390..de16af5b0c2 100644 --- a/src/itree.c +++ b/src/itree.c @@ -725,6 +725,12 @@ interval_tree_validate (struct interval_tree *tree, struct interval_node *node) return node; } +bool +itree_busy_p (void) +{ + return (iter && iter->running); +} + /* Start a generator iterating all intervals in [BEGIN,END) in the given ORDER. Only one iterator per tree can be running at any time. diff --git a/src/itree.h b/src/itree.h index 9e40b87cc4f..7fdc9c07c93 100644 --- a/src/itree.h +++ b/src/itree.h @@ -129,6 +129,7 @@ void interval_tree_iter_finish (struct interval_generator *); struct interval_node *interval_generator_next (struct interval_generator *); void interval_tree_insert_gap (struct interval_tree *, ptrdiff_t, ptrdiff_t); void interval_tree_delete_gap (struct interval_tree *, ptrdiff_t, ptrdiff_t); +bool itree_busy_p (void); /* Iterate over the intervals between BEG and END in the tree T. N will hold successive nodes. ORDER can be one of : `ASCENDING`, @@ -148,9 +149,7 @@ void interval_tree_delete_gap (struct interval_tree *, ptrdiff_t, ptrdiff_t); be able to run ELisp code (or GC for that matter). - If you need to exit the loop early, you *have* to call `ITREE_ABORT` just before exiting (e.g. with `break` or `return`). - - Non-local exits are not supported within the body of the loop, - unless the caller makes sure `ITREE_ABORT` is called via some - kind of unwind_protect. + - Non-local exits are not supported within the body of the loop. - Don't modify the tree during the iteration. */ #define ITREE_FOREACH(n, t, beg, end, order) \