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 alanruttenberg@gmail.com 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 alessiostalla@gmail.com 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 evenson@panix.com wrote:
On Apr 7, 2022, at 08:22, Alessio Stalla alessiostalla@gmail.com
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.
-- "A screaming comes across the sky. It has happened before but there is nothing to compare to it now."