Re: Interrupting repl in Slime
Alan Ruttenberg <[email protected]> Sun, 10 Apr 2022 22:32:16 -0400
| Newsgroups | gmane.editors.j.devel |
|---|---|
| Message-ID | <CAFKQJ8kcqVO-uqLwGypuGrLA5q+WuqapwVmeJZO_jKQWE664JQ@mail.gmail.com> |
Ok, I think I cracked it. Check out https://github.com/armedbear/abcl/pull/482 Alan On Thu, Apr 7, 2022 at 9:26 PM Alan Ruttenberg <[email protected]> wrote: > > Some more: This is where the code for checking for interrupt is generated > (defun maybe-generate-interrupt-check () > (unless (> *speed* *safety*) > (let ((label1 (gensym))) > > * (emit-getstatic +lisp+ "interrupted" :boolean) (emit 'ifeq label1)* > (emit-invokestatic +lisp+ "handleInterrupt" nil nil) > (label label1)))) > > I'm thinking, since interrupt-lisp isn't used anyways, modify it to take a > thread argument. > In interrupt-lisp, call setInterrupted with that thread. > In Lisp.java change the type of interrupted and change setInterrupted to > take a thread argument, setting Lisp.interrupted to it. > > Then, in the maybe-generate-interrupt-check don't Lisp.interrupted check > as boolean, check if eq to current thread. The current thread can be made > accessible adding (ensure-thread-var-initialized), which puts it into a > local at the beginning of the function. Access it with (aload *thread*) > which puts it on the stack. I think this means that the lines underlined > above get replaced with. > > (ensure-thread-var-initialized) > (emit-getstatic +lisp+ "interrupted" +lisp-thread+) > (aload *thread*) > (emit 'if_acmpne label1) > > In Lisp.handleInterrupts it's setInterrupted(null) vs > setInterrrupted(false); > > As stated, this mechanism is strictly to enable control-c. > > However, maybe we could have it help thread-interrupt respond more > quickly. in Lisp.handleInterrupts. > check thread.isInterrupted and call processThreadInterrupts (the thing > that is done now) otherwise break. > Have the implementation of thread-interrupt do what it does now and also > call interrupt-lisp to get it noticed. > --- > > I haven't tried this. Mostly I'm fumbling around trying to get enough > information to do this. I don't know java byte code except what I learned > researching this. > I don't know if there are pitfalls. I don't know why something like this > wouldn't have been done in the first place. > > The only thing I can currently think of is that there could be a race > condition on setting Lisp.interrupted. > The consequence of that is that if there were two quick thread-interrupts, > only one of the threads would > do the quick response. The other would be processed in the way it > currently is. > > Anyways, comments solicited. > Alan > > > > > > On Thu, Apr 7, 2022 at 1:21 PM Alan Ruttenberg <[email protected]> > wrote: > >> The functions that ABCL uses in Threads.java are thread.interrupt and >> thread.isInterrupted. It overrides interrupt and isInterrupted to implement >> interrupt-thread - by saving away the function the target thread is to be >> interrupted with. Remember, interrupt-thread isn't executed by the thread >> to be interrupted, it's called from another thread. The receiving thread >> handles InterruptedException, which is only called on explicit check of >> interrupt state or from sleep or wait. >> >> Separately, in Lisp.Java there's setInterrupted and handleInterrupt that >> don't use the java mechanism. Rather setInterrupted sets a static volatile >> Lisp.interrupted, handleInterrupted clears the variable and calls break. >> setInterrupted, as I said, is only called from interrupt-lisp. Code >> generation inserts checks of Lisp.interrupted and calls handleInterrupted >> if it is set. I have a feeling that this part was done so that frequent >> interrupt checks could be made without taking the performance hit of a >> synchronized method call. Remember this check is done inside every loop >> iteration. The check for Lisp.interrupted is a volatile read, which in most >> cases is handled in the cache. A write to the volatile invalidates the >> cache forcing the new value to be read from memory. So much less expensive. >> >> It would be useful to know the history of how it came to be that there >> are two different interrupt mechanisms. >> >> >> >> On Thu, Apr 7, 2022 at 7:21 AM Alessio Stalla <[email protected]> >> wrote: >> >>> No, I mean >>> https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupted-- >>> >>> The only deprecated methods are suspend, resume and stop. The interrupt >>> machinery is what developers are supposed to use (at least when not using >>> some higher-level framework). It's a form of cooperative multitasking, >>> since a thread can completely ignore the interrupt. However, given we have >>> control over Lisp threads, we can play nice with that convention, and maybe >>> offer a without-interrupts special form for performance-critical code where >>> the developer assumes the responsibility of checking for interrupts in >>> selected moments. >>> >>> On Thu, 7 Apr 2022 at 11:42, Mark Evenson <[email protected]> wrote: >>> >>>> >>>> >>>> > On Apr 7, 2022, at 08:22, Alessio Stalla <[email protected]> >>>> wrote: >>>> > >>>> > […] Java threads already natively have an interrupt flag. >>>> >>>> Presumably, the [Thread.State enumeration] is what you are referring >>>> to. I have checked that it is present in openjdk{8,11,17}, and not marked >>>> as deprecated. >>>> >>>> [1]: >>>> https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html >>>> >>>> -- >>>> "A screaming comes across the sky. It has happened before but there is >>>> nothing >>>> to compare to it now." >>>> >>>> >>>> >>>> >>>> >>>>