Am Do., 17. Nov. 2022 um 14:22 Uhr schrieb Marc Feeley <fee...@iro.umontreal.ca>: > > > > On Nov 11, 2022, at 12:19 PM, Marc Nieper-Wißkirchen > > <marc.nie...@gmail.com> wrote: > > > > I have documented thread-interrupt! in 5.14.6. > > > > Thread-exit! is now renamed to thread-stop!. > > > > I hope that only editorial changes remain before we finalize this. > > > > I have problems understanding the spec for thread-interrupt!: > > (thread-interrupt! thread thunk) procedure > > Schedules an interrupt for thread for when the current-interrupt-level of > thread is zero. The current continuation of thread is then replaced by a > continuation that records the values it receives, invokes thunk with no > arguments, discards its values, and then yields the recorded values to the > original continuation. > > Note: An interrupt can occur while a thread is blocked waiting on a condition > variable. > > > It mentions “replacing” the current continuation of the target thread by a > new one. I don’t understand that model which seems to assume that the > computation moves from continuation to continuation (i.e. that calling a > continuation marks the beginning of a computational step). I think it also > assumes that every point where a continuation is called is a “safe point” > where the Scheme VM is in a consistent state. But when a program is written > in continuation passing style the implicit continuations are never called > because the computation is strictly a sequence of tail calls with no returns. > Also the simple infinite loop (let loop () (loop)) never calls a > continuation… so does that mean it can’t be interrupted?
A continuation is not called; a piece of code is evaluated in a continuation. After each evaluation step (the spec is silent on how fine-grained this is), there will again be a continuation (possibly the same) waiting for the result of some evaluation step. In essence, I mean the same as your syntactic replacement of <expr> by (begin (poll-interrupts!) <expr>). To make it precise, we would really have to amend the formal semantics of Scheme. > I think a better way to explain it is that every expression <expr> in the > program is conceptually treated as (begin (poll-interrupts!) <expr>) and then > give a definition of (poll-interrupts!) that checks the > current-interrupt-level and calls any pending interrupt thunks. Also, the > spec must explain that (for performance reasons) the implementation may > postpone the polling, but only for a bounded time. An interrupt check must > also be performed when the interrupt-level is set to 0, either due to a call > (enable-interrupts!) or (current-interrupt-level 0) or on the way out of a > binding done with (parameterize ((current-interrupt-level …)) …) or on the > way in of a binding done with (parameterize ((current-interrupt-level 0)) …). The latter is, in general, too strict; as the body of parameterize is in tail context when parameterize is in tail context, every return from a call can effectively set the interrupt level to 0, meaning that interrupts would have to be polled at every return. > The second comment is about the note “An interrupt can occur while a thread > is blocked waiting on a condition variable”. A thread can be interrupted in > the “runnable” and “blocked” states, not just blocked on a condition variable > (for example it could be blocked on a mutex, or sleeping). The only > situations where it can’t be interrupted is when the interrupt level is not > 0, or when the state of the thread is “new” (i.e. created but not yet made > runnable) and “terminated”. I called it a "note" precisely because it is not exhaustive. I will expand the note so that there are no misunderstandings. > Finally, the current-interrupt-level mechanism may be too coarse. Perhaps an > interrupt level per interrupt source might be needed for some applications. > I think the current design is OK for now if current-interrupt-level is seen > as a “global” interrupt masking machanism. A future SRFI can add a mechanism > that is more fine-grained. I think this could be implemented on top of the > interrupt mechanism of this SRFI. Having future SRFIs for, say, keyboard or timer interrupts makes sense. Ultimately, a timer would call thread-interrupt! but before, it would have to poll a timer-specific interrupt level parameter. Do you have an idea how to make this polling efficient without further primitives? > I’m slowed down by other things right now so I can’t yet comment on the rest > of SRFI 226. Thank you for your valuable comments so far! I would like to get SRFI 226 finalized within the following weeks.