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

* Re: Making while interruptable
  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-11 19:35 ` Stefan Monnier
  1 sibling, 1 reply; 8+ messages in thread
From: Miles Bader @ 2009-07-06 22:43 UTC (permalink / raw)
  To: Lennart Borgman; +Cc: Emacs-Devel devel

Lennart Borgman <lennart.borgman@gmail.com> writes:
> 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.

This is very, very, bad.  It _will_ screw up lots of code in hard to
debug and confusing ways.

Using a dedicated form like `while-no-input' is proper thing to do.

-Miles

-- 
My spirit felt washed.  With blood.  [Eli Shin, on "The Passion of the Christ"]




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

* Re: Making while interruptable
  2009-07-06 22:43 ` Miles Bader
@ 2009-07-06 23:02   ` Lennart Borgman
  2009-07-06 23:26     ` Miles Bader
  0 siblings, 1 reply; 8+ messages in thread
From: Lennart Borgman @ 2009-07-06 23:02 UTC (permalink / raw)
  To: Miles Bader; +Cc: Emacs-Devel devel

On Tue, Jul 7, 2009 at 12:43 AM, Miles Bader<miles@gnu.org> wrote:
> Lennart Borgman <lennart.borgman@gmail.com> writes:
>> 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.
>
> This is very, very, bad.  It _will_ screw up lots of code in hard to
> debug and confusing ways.

Could you tell me exactly why you think so? Are you aware of that I
placed the code for interruption at the same place as QUIT is placed
in the c code. So I assumed that it was ok to jump out there, but you
seem to think differently. But why? (Don't misunderstand me. I am a
bit afraid of the same things as you, but ...)


> Using a dedicated form like `while-no-input' is proper thing to do.

In the cases I am thinking of you do not have control of this.


> -Miles
>
> --
> My spirit felt washed.  With blood.  [Eli Shin, on "The Passion of the Christ"]
>




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

* Re: Making while interruptable
  2009-07-06 23:02   ` Lennart Borgman
@ 2009-07-06 23:26     ` Miles Bader
  2009-07-06 23:46       ` Lennart Borgman
  0 siblings, 1 reply; 8+ messages in thread
From: Miles Bader @ 2009-07-06 23:26 UTC (permalink / raw)
  To: Lennart Borgman; +Cc: Emacs-Devel devel

Lennart Borgman <lennart.borgman@gmail.com> writes:
>>> 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.
>>
>> This is very, very, bad.  It _will_ screw up lots of code in hard to
>> debug and confusing ways.
>
> Could you tell me exactly why you think so?  Are you aware of that I
> placed the code for interruption at the same place as QUIT is placed
> in the c code. So I assumed that it was ok to jump out there

Most code is not prepared to deal with random non-local control
transfers.  In such cases, a quit _also_ has the potential to screw
something up, but a quit is much much rarer, is explicitly invoked by
the user, and the user knows that after quitting, things may be in a
funny state (it's an emergency action of sorts).  This limits the
problem enough that it's something we can live with.

The mere presence of _input_ on the other hand is _normal_, and your
flag is not connected with any explicit user action.  So with your
system, the number of unexpected non-local control transfers would go
_way_ up, and would not be obviously connected with any user action.

-Miles

-- 
Kilt, n. A costume sometimes worn by Scotchmen [sic] in America and Americans
in Scotland.




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

* Re: Making while interruptable
  2009-07-06 23:26     ` Miles Bader
@ 2009-07-06 23:46       ` Lennart Borgman
  2009-07-06 23:58         ` Miles Bader
  0 siblings, 1 reply; 8+ messages in thread
From: Lennart Borgman @ 2009-07-06 23:46 UTC (permalink / raw)
  To: Miles Bader; +Cc: Emacs-Devel devel

On Tue, Jul 7, 2009 at 1:26 AM, Miles Bader<miles@gnu.org> wrote:
> Lennart Borgman <lennart.borgman@gmail.com> writes:
>>>> 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.
>>>
>>> This is very, very, bad.  It _will_ screw up lots of code in hard to
>>> debug and confusing ways.
>>
>> Could you tell me exactly why you think so?  Are you aware of that I
>> placed the code for interruption at the same place as QUIT is placed
>> in the c code. So I assumed that it was ok to jump out there
>
> Most code is not prepared to deal with random non-local control
> transfers.  In such cases, a quit _also_ has the potential to screw
> something up, but a quit is much much rarer, is explicitly invoked by
> the user, and the user knows that after quitting, things may be in a
> funny state (it's an emergency action of sorts).  This limits the
> problem enough that it's something we can live with.
>
> The mere presence of _input_ on the other hand is _normal_, and your
> flag is not connected with any explicit user action.  So with your
> system, the number of unexpected non-local control transfers would go
> _way_ up, and would not be obviously connected with any user action.

Thanks, yes, that is of course correct. However this mechanism would
just be used only for code that you are running in a timer - in cases
where the code does not explicitly handle pending input. Of course,
changing that code is better, but you can not always do that.




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

* Re: Making while interruptable
  2009-07-06 23:46       ` Lennart Borgman
@ 2009-07-06 23:58         ` Miles Bader
  2009-07-07  0:17           ` Lennart Borgman
  0 siblings, 1 reply; 8+ messages in thread
From: Miles Bader @ 2009-07-06 23:58 UTC (permalink / raw)
  To: Lennart Borgman; +Cc: Emacs-Devel devel

Lennart Borgman <lennart.borgman@gmail.com> writes:
> However this mechanism would just be used only for code that you are
> running in a timer - in cases where the code does not explicitly
> handle pending input. Of course, changing that code is better, but you
> can not always do that.

Nonetheless, the cure seems far worse than the disease.  People writing
timers need to be very careful.  If there are important functions timers
need to call which should be extended to handle user input differently,
then fix those functions, or file a bug, or whatever.  [An implicit
mechanism like you suggest might seem "easier" but it would most likely
not actually work correctly in many cases.]

-Miles

-- 
Electricity, n. The cause of all natural phenomena not known to be caused by
something else.




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

* Re: Making while interruptable
  2009-07-06 23:58         ` Miles Bader
@ 2009-07-07  0:17           ` Lennart Borgman
  0 siblings, 0 replies; 8+ messages in thread
From: Lennart Borgman @ 2009-07-07  0:17 UTC (permalink / raw)
  To: Miles Bader; +Cc: Emacs-Devel devel

On Tue, Jul 7, 2009 at 1:58 AM, Miles Bader<miles@gnu.org> wrote:
> Lennart Borgman <lennart.borgman@gmail.com> writes:
>> However this mechanism would just be used only for code that you are
>> running in a timer - in cases where the code does not explicitly
>> handle pending input. Of course, changing that code is better, but you
>> can not always do that.
>
> Nonetheless, the cure seems far worse than the disease.

I am just trying to be modern. Modern so called scientific medicin
prefers this type of cure. It is good for the economy and therefore by
definition good.

Sigh. Or maybe I have just got too much bad influences (reading to
much incredibly bad peer reviewed medical articles with good
reputation). Or perhaps I am just looking for an excuse that is not
worse than those I have seen in other places. At least I did not hurt
anyone with my suggestion.

Ok. You convinced me that this is not the road forward.

> People writing
> timers need to be very careful.  If there are important functions timers
> need to call which should be extended to handle user input differently,
> then fix those functions, or file a bug, or whatever.  [An implicit
> mechanism like you suggest might seem "easier" but it would most likely
> not actually work correctly in many cases.]
>
> -Miles
>
> --
> Electricity, n. The cause of all natural phenomena not known to be caused by
> something else.
>




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

* Re: Making while interruptable
  2009-07-06 19:40 Making while interruptable Lennart Borgman
  2009-07-06 22:43 ` Miles Bader
@ 2009-07-11 19:35 ` Stefan Monnier
  1 sibling, 0 replies; 8+ messages in thread
From: Stefan Monnier @ 2009-07-11 19:35 UTC (permalink / raw)
  To: Lennart Borgman; +Cc: Emacs-Devel devel

> 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.

Such background tasks are just broken and there's no way to fix
them automatically.  They should either use input-pending-p,
while-no-input, or with-local-quit.


        Stefan




^ 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).