New draft (#2) of SRFI 226: Control Features Arthur A. Gleckler (10 Sep 2022 01:26 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (30 Sep 2022 07:32 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (30 Sep 2022 19:15 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (30 Sep 2022 20:08 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (30 Sep 2022 21:22 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (01 Oct 2022 13:14 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (01 Oct 2022 18:56 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (01 Oct 2022 21:10 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (03 Oct 2022 11:39 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (03 Oct 2022 13:21 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (03 Oct 2022 14:59 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (07 Oct 2022 16:22 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (07 Oct 2022 21:36 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (08 Oct 2022 00:13 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (09 Oct 2022 16:07 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (09 Oct 2022 20:30 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (10 Oct 2022 06:26 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (10 Oct 2022 16:48 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (12 Oct 2022 06:27 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (13 Oct 2022 00:02 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (13 Oct 2022 06:40 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (13 Oct 2022 15:31 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (13 Oct 2022 15:51 UTC)
Re: New draft (#2) of SRFI 226: Control Features Arthur A. Gleckler (30 Sep 2022 23:35 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (27 Oct 2022 06:01 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Feeley (29 Oct 2022 02:54 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (29 Oct 2022 08:13 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Feeley (29 Oct 2022 12:49 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (29 Oct 2022 13:49 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (29 Oct 2022 18:49 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (03 Nov 2022 17:02 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (04 Nov 2022 19:54 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (29 Oct 2022 15:38 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (29 Oct 2022 16:31 UTC)
Re: New draft (#2) of SRFI 226: Control Features John Cowan (29 Oct 2022 21:52 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (30 Oct 2022 08:35 UTC)
Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen (28 Oct 2022 15:17 UTC)

Re: New draft (#2) of SRFI 226: Control Features Marc Nieper-Wißkirchen 30 Oct 2022 08:35 UTC

Am Sa., 29. Okt. 2022 um 23:52 Uhr schrieb John Cowan <xxxxxx@ccil.org>:
>
>
>
> On Sat, Oct 29, 2022 at 12:31 PM Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote:
>
>> Thanks to SRFI 18's notion of abandoned mutexes, you can arrange it so
>> that data structures won't be in an undefined condition. This is, in
>> principle, no harder than arranging that data structures can be shared
>> between two threads.
>
>
>
> Per contra.  Consider a simple double-entry bookkeeping system in which an amount is atomically subtracted from one account A and added to another account B.  Suppose that we use a single global mutex to eliminate issues around deadlock.  Then if a thread is destroyed while holding the mutex, it is possible to tell that the account balances are wrong, but not *how* they are wrong: the amount may have been subtracted from A but not added to B or vice versa, or both, or neither.  It is unsatisfactory to simply give up in these circumstances.

You just have to add a state flag and two shadow cells A' and B'. The
state is initially cleared.  The thread locks the mutex, copies A to
A', and B to B', sets the state, "transfers" the amount from A to B,
clears the state, and unlocks the mutex.  The invariant is that
whenever the state is set, A' and B' hold the old values.  So if
another thread detects an abandoned mutex, it locks it. If the state
flag is set, the thread copies A' and B' into A and B, clears the
state flag, and unlocks the mutex. Otherwise, it just unlocks the
mutex.

A real-world system like a distributed database must also cope with the issues.

If exceptions coming from outside can be raised in the mutator thread,
you will also have to code similarly. You can have an exception
handler around your atomic transfer code, but the exception handler
would have to do the same as I sketched.  And the exception handler
itself could be interrupted at any time.

>
>> In the current semantic model of Scheme (and of SRFI 18 bar
>> extensions), exceptions are synchronously raised in the sense that an
>> exception is only raised during specific evaluations, and which
>> exceptions are raised is documented in the various specifications.
>> Concurrent programming is not impossible in this model.
>
>
> Not impossible, just incomplete in practical terms.

In multi-threaded application code, I have never used signal handlers
to send signals to other threads. The problem is that these signals
can be delivered at any time (e.g. during a money transfer) and not at
an application-specific safe point.  So all you can do is to have the
signal handler (which can't do much in POSIX anyway) set a flag and
let the thread code poll this flag whenever it has arrived at a safe
point.  But then you don't need the signal handler anymore; you can
just have the flag set by the signaling thread.

POSIX/C/C++'s (I don't know about Java) asynchronous signals are far
more limited than what the possibility of raising exceptions at any
time in Scheme would amount to.  And C and C++ are supposed to be
practical programming languages suitable for multi-threading
programming.  (But, of course, we want Scheme to be more practical, so
this is no argument for not adding "asynchronous exceptions").

>> So to implement what you have in mind, the semantic model would have
>> to be extended so that every evaluation step can, in principle, cause
>> an arbitrary exception to be raised.
>
>
> Of course the size of a step does not have to be allowed to be arbitrarily small.  With cooperative cancellation, cancellation happens just when the per-thread cancellation flag is polled.

Are you talking about the scheme evaluator's implementation or the
(high-level) Scheme program itself?

>> I would like to be able to kill a thread that loops forever.
>
>
> I would like it too, but the cost of allowing a thread to be killed at an arbitrary point is too high to pay.

Thread-exit! doesn't have to kill a thread "instantly" (whatever this
means), just eventually.  Only at synchronization points, the temporal
order can be observed (and has to be correct).

~~~~

Let me sketch the proposals that are floating around (and correct me
if I have misunderstood a thing).  Then we can refine them so that we
get the details right and so that there is no danger of talking past
each other:

(1) A procedure (thread-exit! THREAD).  This works like SRFI 18's
`thread-terminate!' except that it returns immediately.  The abnormal
termination of a thread happens asynchronously as long as the
observable sequence of events remains consistent. SRFI 18's concept of
abandoned mutexes is used to prevent critical data structures from
entering an undefined state.

(2) A procedure like "(thread-raise! THREAD CONDITION)".  This
procedure causes the evaluator of THREAD to raise a non-continuable
exception with condition object CONDITION at some
implementation-defined safe point (subject to the same sequential
constraints as in (1)).  This means that, in principle, any evaluation
step may proceed with running the code of the current exception
handler.

(3) A procedure like (thread-signal! THREAD SIGNAL [TIMEOUT]).  This
procedure causes the evaluator of THREAD to pause its current
evaluation and to invoke THREAD's *signal handler* (a new concept,
similar to an exception handler) in the dynamic environment where the
current evaluation is paused.  When the signal handler returns, its
results are delivered to the caller of `thread-signal!` and the paused
evaluation of THREAD is continued.  One needs an accompanying
procedure like `with-signal-handler'.

(4) A procedure like (thread-interrupt! THREAD THUNK [TIMEOUT]).  This
procedure causes the evaluator of THREAD to pause its current
evaluation.  It then invokes THUNK in the dynamic environment where
the current evaluation is paused.  When the THUNK returns, its results
are delivered to the caller of `thread-interrupt!' and the paused
evaluation of THREAD is continued.

(5) A procedure like (current-thread-exit!) that is like
"thread-exit!" but only for the current thread.