aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2017-02-05 13:25:37 -0800
committerPaul Eggert2017-02-05 13:30:29 -0800
commitb491322ed0fcf039669183880a342bbb2326e787 (patch)
treed72d9396783d63214a8ab1069f972bb3029921f0 /src
parent14dd9101ec4838f75addf25bf6b06ef33f8a7e97 (diff)
downloademacs-b491322ed0fcf039669183880a342bbb2326e787.tar.gz
emacs-b491322ed0fcf039669183880a342bbb2326e787.zip
FOR_EACH_TAIL now checks for quit
As per Eli Zaretskii (Bug#25606#20). Although these calls to maybe_quit are unnecessary in practice, Eli was not convinced that the calls are unnecessary. * src/lisp.h (FOR_EACH_TAIL, FOR_EACH_TAIL_CONS): Call maybe_quit every so often. (FOR_EACH_TAIL_INTERNAL): New arg CHECK_QUIT. All callers changed.
Diffstat (limited to 'src')
-rw-r--r--src/lisp.h52
1 files changed, 32 insertions, 20 deletions
diff --git a/src/lisp.h b/src/lisp.h
index 13fca0b29e0..edbd15170f8 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4580,44 +4580,56 @@ enum
4580 Lisp_String)) \ 4580 Lisp_String)) \
4581 : make_unibyte_string (str, len)) 4581 : make_unibyte_string (str, len))
4582 4582
4583/* Loop over tails of LIST, checking for dotted lists and cycles. 4583/* Loop over tails of LIST, checking for dotted lists and cycles,
4584 and possibly quitting after each loop iteration.
4584 In the loop body, ‘li.tail’ is the current cons; the name ‘li’ is 4585 In the loop body, ‘li.tail’ is the current cons; the name ‘li’ is
4585 short for “list iterator”. The expression LIST may be evaluated 4586 short for “list iterator”. The expression LIST may be evaluated
4586 more than once, and so should not have side effects. The loop body 4587 more than once, and so should not have side effects. The loop body
4587 should not modify the list’s top level structure other than by 4588 should not modify the list’s top level structure other than by
4588 perhaps deleting the current cons. 4589 perhaps deleting the current cons. */
4589
4590 Use Brent’s teleporting tortoise-hare algorithm. See:
4591 Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190
4592 http://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf */
4593 4590
4594#define FOR_EACH_TAIL(list) \ 4591#define FOR_EACH_TAIL(list) \
4595 FOR_EACH_TAIL_INTERNAL (list, CHECK_LIST_END (li.tail, list), \ 4592 FOR_EACH_TAIL_INTERNAL (list, CHECK_LIST_END (li.tail, list), \
4596 circular_list (list)) 4593 circular_list (list), true)
4597 4594
4598/* Like FOR_EACH_TAIL (LIST), except check only for cycles. */ 4595/* Like FOR_EACH_TAIL (LIST), except do not check for dotted lists. */
4599 4596
4600#define FOR_EACH_TAIL_CONS(list) \ 4597#define FOR_EACH_TAIL_CONS(list) \
4601 FOR_EACH_TAIL_INTERNAL (list, (void) 0, circular_list (list)) 4598 FOR_EACH_TAIL_INTERNAL (list, (void) 0, circular_list (list), true)
4602 4599
4603/* Like FOR_EACH_TAIL (LIST), except check for neither dotted lists 4600/* Like FOR_EACH_TAIL (LIST), except check for neither dotted lists
4604 nor cycles. */ 4601 nor cycles, and do not quit. */
4605 4602
4606#define FOR_EACH_TAIL_SAFE(list) \ 4603#define FOR_EACH_TAIL_SAFE(list) \
4607 FOR_EACH_TAIL_INTERNAL (list, (void) 0, (void) (li.tail = Qnil)) 4604 FOR_EACH_TAIL_INTERNAL (list, (void) 0, (void) (li.tail = Qnil), false)
4608 4605
4609/* Like FOR_EACH_TAIL (LIST), except evaluate DOTTED or CYCLE, 4606/* Like FOR_EACH_TAIL (LIST), except evaluate DOTTED or CYCLE,
4610 respectively, if a dotted list or cycle is found. This is an 4607 respectively, if a dotted list or cycle is found, and check for
4611 internal macro intended for use only by the above macros. */ 4608 quit if CHECK_QUIT. This is an internal macro intended for use
4609 only by the above macros.
4612 4610
4613#define FOR_EACH_TAIL_INTERNAL(list, dotted, cycle) \ 4611 Use Brent’s teleporting tortoise-hare algorithm. See:
4614 for (struct { Lisp_Object tail, tortoise; intptr_t n, max; } li \ 4612 Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190
4615 = { list, list, 2, 2 }; \ 4613 http://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf
4614
4615 This macro uses maybe_quit because of an excess of caution. The
4616 call to maybe_quit should not be needed in practice, as a very long
4617 list, whether circular or not, will cause Emacs to be so slow in
4618 other noninterruptible areas (e.g., garbage collection) that there
4619 is little point to calling maybe_quit here. */
4620
4621#define FOR_EACH_TAIL_INTERNAL(list, dotted, cycle, check_quit) \
4622 for (struct { Lisp_Object tail, tortoise; intptr_t max, n; \
4623 unsigned short int q; \
4624 } li = { list, list, 2, 0, 2 }; \
4616 CONSP (li.tail) || (dotted, false); \ 4625 CONSP (li.tail) || (dotted, false); \
4617 (li.tail = XCDR (li.tail), \ 4626 (li.tail = XCDR (li.tail), \
4618 (li.n-- == 0 \ 4627 ((--li.q != 0 \
4619 ? (void) (li.n = li.max <<= 1, li.tortoise = li.tail) \ 4628 || ((check_quit) ? maybe_quit () : (void) 0, 0 < --li.n) \
4620 : EQ (li.tail, li.tortoise) ? (cycle) : (void) 0))) 4629 || (li.q = li.n = li.max <<= 1, li.n >>= USHRT_WIDTH, \
4630 li.tortoise = li.tail, false)) \
4631 && EQ (li.tail, li.tortoise)) \
4632 ? (cycle) : (void) 0))
4621 4633
4622/* Do a `for' loop over alist values. */ 4634/* Do a `for' loop over alist values. */
4623 4635