unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Making while interruptable
@ 2009-07-06 19:40 Lennart Borgman
  2009-07-06 22:43 ` Miles Bader
  2009-07-11 19:35 ` Stefan Monnier
  0 siblings, 2 replies; 8+ messages in thread
From: Lennart Borgman @ 2009-07-06 19:40 UTC (permalink / raw)
  To: Emacs-Devel devel

[-- Attachment #1: Type: text/plain, Size: 838 bytes --]

Hi have been playing a bit with some thoughts about making `while'
look for input, sort of `while-no-input', but a bit more general. I
took the c code and changed it a bit to see how it looked. The idea is
that the user with some let bound variable can control how every call
to `while' handles pending input. If pending input is detected then
`while' will throw to a catch symbol that is let bound by the user.

I do not know if this is useable (the code is not yet, need some
fixes, I am not good at c). The drawback might be too much overhead.
Also some code might leave things in a bad state if a throw happens in
`while'.

The advantage is of course that it could make Emacs feel more alive
with back ground parsers and other jobs in the background that did not
care to call input-pending-p.

I have attached the code. Any thoughts?

[-- Attachment #2: while-not-input.c --]
[-- Type: text/plain, Size: 3991 bytes --]

DEFVAR_INT ("while-time-interval", &while_time_interval,
            doc: /* Check for input during while after this number of millisec.
If equal or less than 0 do not check for input.
You are supposed to let bind this variable for code where you want this check.

See also `while-throw-values'. If this is nil do not check for input. */);
  while_time_interval = 0;

DEFVAR_LISP ("while-throw-values", &Vwhile_throw_values,
             doc: /* List with catch symbol and value to throw during while.
If input arrives during `while' then `throw' to symbol and value in this list.

Optionally the list may contain a third element, if the list contains a third element then this should be a symbol.  Throw then happens only if this variable symbol is non-nil, or, if it is a function if it returns non-nil.

The full format of this variable is

   \(CATCH-SYM VALUE-SYM TEST-SYM)

where TEST-SYM is optional.

See also `while-time-interval' for when the test for input availability is done.
*/);
Vwhile_throw_values = Qnil;

DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0,
       doc: /* If TEST yields non-nil, eval BODY... and repeat.
The order of execution is thus TEST, BODY, TEST, BODY and so on
until TEST returns nil.
usage: (while TEST BODY...)

The execution can be interrupted by input.  See `while-time-interval'
for more information.  */)
     (args)
     Lisp_Object args;
{
  Lisp_Object test, body;
  struct gcpro gcpro1, gcpro2;
  EMACS_TIME t;
  time_t sec;
  int usec;
  time_t sec_next;
  int usec_next;
  int check_input = (while_time_interval > 0) && Flistp (Vwhile_throw_values);
  Lisp_Object catch_sym, value_sym, test_sym, value_sym_value;

  if (check_input)
    {
      /* Check Vwhile_trhow and while_time_interval value types
         first! */
      catch_sym = Fnth (0, Vwhile_throw_values);
      value_sym = Fnth (1, Vwhile_throw_values);
      test_sym  = Fnth (2, Vwhile_throw_values);
      check_input = Fsymbolp (catch_sym)
        && (NILP (test_sym)  || (Fsymbolp (test_sym)  && (Fboundp (test_sym)  || Ffboundp (test_sym))))
        && (NILP (value_sym) || (Fsymbolp (value_sym) && (Fboundp (value_sym) || Ffboundp (value_sym))));
      if (check_input)
        {
          EMACS_GET_TIME (t);
          usec = EMACS_USECS (t);
          sec = EMACS_SECS (t);
          sec_next = sec;
          usec_next = usec + while_time_interval;
          if (usec_next > 1000)
            {
              /* Fix-me: what are the op in c?? */
              sec_next = usec_next % 1000;
              usec_next = use_next mod 1000;
            }
        }
    }

  GCPRO2 (test, body);

  test = Fcar (args);
  body = Fcdr (args);
  while (!NILP (Feval (test)))
    {
      QUIT;
      /* Maybe not check time every time? */
      if (check_input)
        {
          EMACS_GET_TIME (t);
          usec = EMACS_USECS (t);
          sec = EMACS_SECS (t);
          if (sec > sec_next || usec > usec_next)
            {
              if ((NILP (test_sym)
                   ||
                   !NILP (Fboundp (test_sym) ? Fsymbol_value (test_sym) : Fcall0 (test_sym)))
                  &&
                  Finput_pending_p ())
                {
                  value_sym_value = (Fboundp (value_sym) ?
                                     Fsymbol_value (value_sym) :
                                     (Ffboundp (value_sym) ?
                                      Fcall0 (value_sym) :
                                      value_sym));
                  Fthrow (catch_sym, value_sym_value);
                }
              sec_next = sec;
              usec_next = usec + while_time_interval;
              if (usec_next > 1000)
                {
                  sec_next = usec_next % 1000;
                  usec_next = use_next mod 1000;
                }
            }
        }
      Fprogn (body);
    }

  UNGCPRO;
  return Qnil;
}

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-07-11 19:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-06 19:40 Making while interruptable Lennart Borgman
2009-07-06 22:43 ` Miles Bader
2009-07-06 23:02   ` Lennart Borgman
2009-07-06 23:26     ` Miles Bader
2009-07-06 23:46       ` Lennart Borgman
2009-07-06 23:58         ` Miles Bader
2009-07-07  0:17           ` Lennart Borgman
2009-07-11 19:35 ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).